Commit graph

4 commits

Author SHA1 Message Date
Deluan
8789561b60 fix(api): consolidate grant deletes and harden API v1 auth after review
- GrantRepository keeps three deletes: DeleteForUser, DeleteStaleEpochs
  (replaces DeleteOtherEpochs and DeleteIfEpoch) and DeleteIdle. Delete(id)
  is gone; the idle path in ResolveGrant now calls DeleteIdle, so a grant
  renewed by another node between the read and the delete survives.
  settleEpoch deletes the user's grants below the snapshot's epoch, which
  is safe outside the transaction because epochs only move forward.
- The "dead grants on an older epoch are only deleted when presented"
  policy note moves from the repository to core ListGrants.
- SQL trace logging no longer prints the args of property writes (signing
  keys) or user password writes, both encrypted with a key that may be the
  public default. The SQL statement is still logged.
- The spec gate rejects JSON body keys that differ from a declared property
  only in case. kin-openapi validates exact names while encoding/json
  decodes case-insensitively, so {"scopes":[],"Scopes":null} minted a
  token with every scope and a "Client" key skipped maxLength.
  It also rejects data after the first JSON value, which the handlers'
  decoder ignores and which let a body skip the alias check.
- The liveness cache trims its eviction log on evict, not only on put, so
  evict-only traffic stays bounded; the floor still drops stale fills.
- createAccessToken, login and setupFirstAdmin declare Cache-Control:
  no-store on their success responses.
2026-09-28 20:06:28 -04:00
Deluan
a41e656706 refactor(api): reuse existing helpers in API v1 auth
Use gg.V, slice.Map, chi's RequestSize, core/auth's encryption key and
ClientIPRateLimiter instead of local copies; share the grant idle expiry
constant and a Grant.LastActivity helper; pass last use as a time value.
2026-09-28 20:06:28 -04:00
Deluan
b1cfa932be fix(api): make logout idempotent and hide grants left on a stale epoch
Logout answered an undeclared 404 when its grant was already gone, for
example revoked by another node inside the liveness cache window or by a
concurrent logout. It now treats a missing grant as success and still
evicts the cache entry, so logout always answers 200.

Grants left on an older user epoch (after a password reset through the
existing UI, or a login that raced a password change) are dead but only
deleted when presented. Listing and counting grants now filter on the
user's current epoch, so those grants no longer show up.

dropGrant now deletes before evicting, like RevokeGrant, so a concurrent
cache fill cannot re-cache a grant that is being dropped.
2026-09-28 20:06:28 -04:00
Deluan
2afe2ffe0a feat(api): add api_grant storage for API v1 grants 2026-09-28 20:06:27 -04:00