feat(web): hashed API credential registry for request-time auth - #429
feat(web): hashed API credential registry for request-time auth#429cursor[bot] wants to merge 1 commit into
Conversation
Request-time auth now reads api_credentials only. CODEC_CARVER_API_KEYS is bootstrap transport into SHA-256 digests compared with hmac.compare_digest across the full active set. GET /health stays auth-exempt for probes. Closes the #329/#373 request-time env gap without mixing Cloud Agent environment work from #426/#427. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
There was a problem hiding this comment.
This is the credential-registry landing vehicle for #329/#373. Head d3f0280 moves request-time auth off os.getenv("CODEC_CARVER_API_KEYS") onto hashed api_credentials.
Next actions:
- Keep #427 as the Cloud Agent environment head. Do not merge #426 at
8a60d4a. - After #427 is the named env tip, rebase this PR onto it. Both add
GET /healthandARCHITECTURE.md. - Do not merge HMAC-only #376/#421 in parallel; this PR covers the Unicode
compare_digestpath. - Do not mix drop-zone (#428) or
jobs→conversion_jobshere. - Do not self-approve. Wait for required checks on this head.
Sent by Cursor Automation: Fix Issues
There was a problem hiding this comment.
Useful first slice (hashed api_credentials, lifespan bootstrap, auth-exempt GET /health), but do not land this in parallel with #430.
#430 already covers the #373 gaps this body deferred: fail-closed 0.0.0.0 without keys, credential_events audit, and public listings that omit digests. Merging both will conflict on the registry API.
Do this next:
- Prefer #430 (
5a80b18) as the credential landing vehicle. Close or supersede this draft after that head is named. - Keep
verify→credential_idas the idea to port onto #430 so usage metering can drop plaintextapi_key. - Do not mix drop-zone (#428) or Cloud Agent env (#426/#427) into this branch.
- Do not self-approve.
Sent by Cursor Automation: Fix Issues
Port the two #429 ideas onto this head: verify yields the stable credential_id for usage metering, and FastAPI lifespan runs the named bootstrap instead of a deprecated startup event. Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
|
Closing as superseded by #430. The current #430 lineage explicitly ports the remaining #429 ideas—FastAPI lifespan bootstrap and |


What
Request-time SaaS authentication reads a stdlib SQLite registry (
credential_registry.py, tableapi_credentials) instead ofos.getenv("CODEC_CARVER_API_KEYS").bootstrap_from_mappingat process start (FastAPI lifespan). The env var is not read inside request handlers.active/rotated/revoked) and optional expiry. Callers passnow.hmac.compare_digestso first-match timing is not a signal and mixed str/bytes cannot raiseTypeErroron hostile Unicode.GET /healthreturns{"status":"ok","service":"codec-carver"}and stays auth-exempt so probes can confirm the process is up.docs/doctoring/api-credential-registry.md(APA 7: NIST SP 800-63B, RFC 2104, OWASP API Security Top 10 2023).Why
Issues #329 and #373. AGENTS.md forbids request-time env secrets. This is the next buyer-visible gap after the Cloud Agent environment work.
Validation
python3 -m unittest tests.test_credential_registry tests.test_saas_web -v— 108 passedpython3 -m coverage report --include=credential_registry.py,saas_web.py— 100%python3 -m interrogate credential_registry.py saas_web.py— 100%python3 -m py_compile credential_registry.py saas_web.py— OKNotes
8a60d4a.jobs→conversion_jobsinto this PR.