C.W.K.
Stream
Lesson 01 of 06 · published

The Architecture in One Picture

~15 min · architecture, schema, middleware

Level 0Greenhorn
0 XP0/53 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

The PIN layer is a small, self-contained authentication system that fits behind any web framework. It exists to add per-request authentication inside the trusted perimeter (Tailscale), so that even when the perimeter cracks, you still have a lock.

The pieces

ComponentWhat it doesWhere it lives
MiddlewareGates every request: bypass / session-check / redirect to loginWeb framework's request pipeline
SQLite tablesConfig (PIN hash, settings), sessions, blacklist, retry attemptsOne file on disk
Login endpointVerifies PIN, issues a session cookie, increments retry counter on failPOST /login
Logout endpointDeletes the session row, clears the cookiePOST /logout
Admin endpointsList sessions, manage blacklist, "Revoke All" killswitch/admin/security/* (Track 8)

The whole schema

Four tables, no joins, no migrations needed. The next lessons walk through each component in the order requests touch them.

Code

The middleware request flow·text
incoming request
   |
   v
[Middleware]
   |
   |--- public path (login, health, static)? ---> pass through
   |
   |--- source IP in LOCAL_BYPASS list? ---------> pass through
   |
   |--- source IP in blacklist? -----------------> 403 Forbidden
   |
   |--- session cookie present and valid? -------> attach user, pass through
   |
   |--- otherwise --------------------------------> redirect to /login
The full SQLite schema for the PIN layer·sql
-- Config: one row, holds the PIN hash and policy
CREATE TABLE security_config (
  id              INTEGER PRIMARY KEY CHECK (id = 1),
  pin_hash        TEXT    NOT NULL,
  pin_enabled     INTEGER NOT NULL DEFAULT 1,
  max_retry       INTEGER NOT NULL DEFAULT 5,
  session_seconds INTEGER NOT NULL DEFAULT 2592000   -- 30 days
);

-- Active sessions
CREATE TABLE security_sessions (
  token       TEXT PRIMARY KEY,
  ip          TEXT    NOT NULL,
  created_at  INTEGER NOT NULL,
  expires_at  INTEGER NOT NULL
);

-- Per-IP retry counter
CREATE TABLE security_attempts (
  ip          TEXT PRIMARY KEY,
  fail_count  INTEGER NOT NULL DEFAULT 0,
  updated_at  INTEGER NOT NULL
);

-- IP blacklist
CREATE TABLE security_blacklist (
  ip          TEXT PRIMARY KEY,
  reason      TEXT,
  blocked_at  INTEGER NOT NULL
);

External links

Exercise

Create security.db and run the four CREATE TABLE statements above (sqlite3 security.db < schema.sql). Insert a test config row with a placeholder pin_hash (we set the real one in the next lesson). The exercise: confirm SQLite is on your machine, the tables exist, and you can query them.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.