feat(persistence): saved diagram views + table annotations#467
Open
seonghobae wants to merge 8 commits into
Open
feat(persistence): saved diagram views + table annotations#467seonghobae wants to merge 8 commits into
seonghobae wants to merge 8 commits into
Conversation
Split out of the adhesive-piper foundation as an independent PR against main. Two persisted entities sharing the alembic chain (0004_merge_heads resolves main's two 0003 heads -> 0005_diagram_view -> 0006_table_annotation), models.py, and router registration. /api/diagram-views (save/load ERD canvas layouts) and /api/annotations (per-table notes), both editor-gated + IDOR-safe uniform 404. +8 tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd
This was referenced Jul 5, 2026
Closed
Stacked on #467 (needs TableAnnotation); auto-retargets to main when #467 merges. GET /api/snapshots/{uuid}/data-dictionary.md renders a dialect-agnostic Markdown data dictionary (schema sections, columns table, FKs, indexes, view labels) merged with the project's table annotations. IDOR-safe. Frontend download button follows once the frontend foundation lands. +tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd
P2 roadmap item — API-first platform access. Bearer pgerd_* keys accepted by get_current_user alongside OIDC (non-invasive branch). Secrets never stored: SHA-256 hash only, plaintext returned exactly once at creation, key_prefix for recognition, revocation is an auditable timestamp (idempotent). /api/api-keys: POST create, GET list (metadata only), DELETE revoke (uniform 404 for other users' keys). Also carries the 0003_revoked_token down_revision fix ('0002' -> '0002_auth_share') without which alembic upgrade head breaks on a fresh DB. Migration 0007 verified against real Postgres. +5 tests; backend suite 236; mypy clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd
…hare down_revision='0002' references a nonexistent revision (actual id 0002_auth_share); alembic upgrade head fails with KeyError '0002' on a fresh DB. Latent on main; surfaces once this PR's 0004_merge_heads chain is walked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd
feat(docs): data dictionary export (backend)
feat(platform): API keys for programmatic access
| def hash_api_key(token: str) -> str: | ||
| """Deterministic SHA-256 hex digest of an API key (indexable lookup).""" | ||
|
|
||
| return hashlib.sha256(token.encode("utf-8")).hexdigest() |
Collaborator
Author
There was a problem hiding this comment.
Addressed in 45599e8 with an explanatory docstring rather than a KDF swap: the hashed input is a server-generated 256-bit random token (secrets.token_urlsafe(32)), not a human password — brute force over the input space is infeasible, and a slow KDF (bcrypt/argon2) would add cost without security while breaking the unique-indexed O(1) lookup that deterministic digests provide. This mirrors GitHub's own PAT storage scheme.
Addresses github-code-quality r3531583397 (unused 'patch') and CodeQL r3531597887: the hashed value is a server-generated 256-bit random token, not a password — a slow KDF adds nothing and a deterministic digest is required for the unique-indexed lookup (same scheme GitHub uses for PATs). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AxU2xaupAjp912oDNFuWyd
# Conflicts: # backend/app/api/snapshots.py # backend/app/schemas.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Independent PR against
main(split out of #440). Now also contains the merged stack: #469 (data dictionary export) and #485 (API keys).0004_merge_heads→0005→0006, editor-gated, IDOR-safe)GET /data-dictionary.md— Markdown data dictionary merged with annotations (living documentation)/api/api-keys,Bearer pgerd_…inget_current_user): SHA-256 hash only, secret shown once, auditable revocation, uniform 404; migration0007_api_keyverified on real Postgres; also fixes the latent0003_revoked_tokendown_revision bug that breaksalembic upgrade headon fresh DBsbackend tests incl. IDOR/editor gates; mypy clean.
🤖 Generated with Claude Code