Skip to content

Feat/tier3 config and endpoints - #5

Merged
raymondproguy merged 10 commits into
mainfrom
feat/tier3-config-and-endpoints
Sep 15, 2026
Merged

raymondproguy merged 10 commits into
mainfrom
feat/tier3-config-and-endpoints

Conversation

@raymondproguy

Copy link
Copy Markdown
Contributor

No description provided.

raymondproguy and others added 10 commits September 15, 2026 12:23
Tier 3's admin endpoints need store instances cryden.Engine keeps
unexported, so they can only come from whoever built them. A Deps
struct absorbs that without growing every call site positionally.

Co-Authored-By: Claude Code <noreply@anthropic.com>
PASSWORD_HASHER selects argon2id; ARGON2ID_* each override one field of
cryden's defaults, since the engine treats a partial struct as a real
configuration rather than defaults-plus-overrides. LOG_LEVEL goes
through logger.ParseLevel so a typo fails startup instead of silently
falling back to debug.

EMAIL_TEMPLATE_DIR adds templates/, this repo's own copy — cryden owns
no message copy on purpose.

Co-Authored-By: Claude Code <noreply@anthropic.com>
POST/GET /v1/api-keys and DELETE /v1/api-keys/{keyID}, all behind
RequireAuth. cryden derives the user ID from the verified token and
scopes every store call by it, so a caller can never read or revoke
another account's key.

The raw key is returned exactly once, with a notice saying so — cryden
stores only its hash. expires_in_days is bounded so a large value cannot
overflow the duration into a negative TTL.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Read-only, behind RequireAdmin. Reports what the deployment is
configured to write, the user total, and the all-time and 7-day counts
of the engine's own password_hash_upgraded audit events.

upgraded_events counts events, not users, so it can exceed total_users —
estimated_remaining is floored at zero and named "estimated" for that
reason. main.go now hoists its user and audit stores so the report
counts the same instances the engine writes through.

Co-Authored-By: Claude Code <noreply@anthropic.com>
README and openapi/spec.yaml cover the new env vars, the API key
endpoints and the hash-migration report — including why
upgraded_events counts events rather than users.

PROGRESS.md records the Stage 1 verification run and the four commits
it landed as.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Adds user_metadata (migrations/009) and the usermeta package: cryden's
store.User has no metadata concept, so per CLAUDE.md's ownership rule the
table and its rules are this repo's own.

The store owns key validation, not the handler, because a metadata key is
a claim name: a key of "sub" would not be ignored at login, it would fail
the login, and a key of "role" would mint an operator token for a user the
operators table has never heard of — access operator.Store.Revoke could
not take away. Both are refused where an operator can still see why.

Admin endpoints behind RequireAdmin, one key per call so no
read-modify-write race exists for a console to lose:
  GET    /v1/admin/users/{userID}/metadata
  PUT    /v1/admin/users/{userID}/metadata/{key}
  DELETE /v1/admin/users/{userID}/metadata/{key}

All three answer the same body, so a save is also the refresh, and the
reserved names are listed so a claim-mapping UI can grey them out.
usermeta.ClaimsProvider owns the merge into Config.AccessTokenClaims —
two queries per login and per refresh, which is the price of claims that
are current rather than frozen at signup.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Engine events are enqueued into this repo's own table and delivered by a
background worker, never inline on cryden's login request path.

Co-Authored-By: Claude Code <noreply@anthropic.com>
The redacted, filtered copy the cloud sink is handed is recorded in this
repo's own table — the stand-in for a hosted aggregator, which this repo
has no client for. GET /v1/admin/logging/recent (admin) reads it back.

Co-Authored-By: Claude Code <noreply@anthropic.com>
README gains User metadata, Webhooks and Cloud logging / shipped events
sections, plus design notes on the three repo-owned tables, the read-only
admin surface and the missing graceful shutdown. spec.yaml goes to 1.3 with
the three new admin groups. Its APIKey id description contained unquoted
braces inside a flow mapping, so the file had never parsed — fixed here.

Co-Authored-By: Claude Code <noreply@anthropic.com>
Marks Tier 3 done in NEXT.md, adds its section to CURRENT-STATE.md and
logs the session in PROGRESS.md. The entry says plainly what a green
suite does not cover here: no Postgres, so migrations 009-011 have never
been applied; the worker's SKIP LOCKED claim is untested; the in-memory
double cannot reproduce two workers racing.

Co-Authored-By: Claude Code <noreply@anthropic.com>
@raymondproguy
raymondproguy merged commit 8c6f0f2 into main Sep 15, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant