From 10d6e3065378fc5578fb9dd066235ba8f0b6040e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 1 Sep 2026 21:05:38 +0900 Subject: [PATCH 01/10] docs: consolidate the product & technical gap baseline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New docs/product-technical-gap-baseline.md โ€” the single tracker for the distance between pg-erd-cloud today and a defensible first commercial release. - Names the active commercial-readiness blocker: org CI incident ContextualWisdomLab/.github#1531 (0 pg-erd-cloud main merges since 2026-08-20; 10 merge-ready loop PRs stacked and waiting). - One section per open gap/epic issue #946-#953: Feature spec (summary) | Current state | Gap | This loop's increment PRs | Remaining increments | Status. - Maps the loop's shipped increments to their issues: #1031/#1032/#1033/#1035 (#947), #1036 (#951), #1037 (#946), #1038 (#948), #1039 (#950); #1024/#1025 as release-hygiene prerequisites for #953. - Cross-repo / ecosystem table (keyverse, contextual-orchestrator, wardnet, central .github; TEPP/fast-mlsirm noted as not consumed) + a status legend. Supersedes and extends the draft in PR #942 (blocked by the incident); the two reconcile when either merges. #949 / #952 / #953 sections are lighter this pass (GitHub API was rate-limited during the read) and will be filled in next. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 1 + docs/product-technical-gap-baseline.md | 344 +++++++++++++++++++++++++ 2 files changed, 345 insertions(+) create mode 100644 docs/product-technical-gap-baseline.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 35613431a..676fb5dca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## Unreleased +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready PR 10๊ฑด ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1036/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€๋ฅผ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md new file mode 100644 index 000000000..1f6b0701f --- /dev/null +++ b/docs/product-technical-gap-baseline.md @@ -0,0 +1,344 @@ +# Product & technical gap baseline + +**Last consolidated:** 2026-09-01 (autonomous review/merge loop, iter14). + +This document is the single tracker for the distance between what +pg-erd-cloud does today and a defensible first commercial release. It is +derived from the open `[Product Gap]` / `[Enterprise Gap]` / `[Performance +Gap]` / `[Security Gap]` / `[Epic]` issues (#946โ€“#953), the code on +`main@8dc74692`, and the in-flight PRs that close pieces of each gap. + +It supersedes the draft in PR #942 (which first introduces this file and is +currently blocked โ€” see the commercial-readiness blocker below); the two +should be reconciled when either merges. + +## What pg-erd-cloud is + +A PostgreSQL-focused cloud ERD collaboration service. It reverse-engineers a +target database into immutable JSON schema snapshots, renders them as an +interactive ERD (React Flow), and forward-engineers snapshots into DDL +exports, schema diffs / migration SQL, DBML / Mermaid exports, and reversing +spec documents. Project owners can create read-only share links. + +## Commercial-readiness bar + +A buyer must be able to verify, from product-owned evidence, that: (1) schema +quality claims are backed by catalog or measured evidence, not heuristics; +(2) the deployment's isolation boundary is described accurately and enforced; +(3) large-schema behaviour has a published capacity envelope; (4) credential +lifecycle is auditable; (5) forward-engineering apply is governed with +rollback; (6) every release carries exact-head, migration, operability, and +supply-chain evidence. + +## Commercial-readiness blocker (active incident) + +**`ContextualWisdomLab/pg-erd-cloud` `main` has merged nothing since +2026-08-20.** Root cause: `ContextualWisdomLab/.github` GitHub Actions queue +saturation (`.github#1531`). The central required check `opencode-review` +dispatches a review to `.github` and polls ~90 min for a current-head +verdict; with ~800โ€“900 runs queued org-wide the verdict does not arrive and +the check fails closed on every PR. A parallel remediation effort owns +`.github#1531`; a related `head_sha` TOCTOU in `opencode-review-dispatch.yml` +was found and is being addressed in that repo. + +**Consequence for this baseline:** every gap increment below is shipped as a +small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until +the gate clears. As of iter14 the loop has 10 such PRs stacked +(#942, #1024, #1025, #1031, #1032, #1033, #1035, #1036, #1037, #1038, #1039). + +## Status legend + +| status | meaning | +| --- | --- | +| `spec'd` | issue defines the contract; no code yet | +| `in-progress` | โ‰ฅ1 increment shipped as a merge-ready PR; more increments remain | +| `merge-ready-blocked` | code complete for this increment; waiting on the gate | +| `not-started` | no work this loop | + +--- + +## #946 โ€” Auditable credential-provider contract (`[Security/Product Gap]`) + +**Feature spec (summary).** Replace unaudited runtime env/`.env` secret +transport with a provider-neutral `CredentialProvider` / `SecretReference` +boundary: bootstrap transport only, no plaintext in ORM rows / logs / traces / +metrics / repr; local mounted-file + org-registry + deterministic-test +providers; dual-read / single-write `APP_SECRET` rotation; fail-closed on +missing / revoked / expired / symlinked / oversized / malformed material; +recovery runbook proving key-unavailable recovery cannot expose DSN plaintext. + +**Current state.** `Settings` builds directly from env / `.env`. +`APP_SECRET_FILE` is a fail-closed `/run/secrets` seam but every other +credential (DB, OIDC, LLM, Clearfolio HMAC, metrics, Valkey) is unmanaged +runtime config. + +**Gap.** No single auditable credential lifecycle; no rotation; no access +attribution. + +**This loop's increment PRs.** +- **#1037** โ€” `app/secret_provider/`: typed `CredentialProvider` Protocol, + `SecretReference` (no value), `ResolvedSecret` (value only via `reveal()`; + `str`/`repr`/`format`/logs redact), fail-closed `SecretResolutionError`, + `LocalMountedFileProvider` (fail-closed on missing/empty/oversized/non-UTF8/ + symlink/path-escape/non-file), `DeterministicTestProvider`. 14 tests incl. + "value never appears in str/repr/format/logs". Rotation design documented. + +**Remaining increments.** `Settings` integration behind a `local_secret_file` +profile; org credential-registry provider with cache-TTL + fail-closed +timeout/permission/revoked/stale; implement `APP_SECRET` dual-read rotation + +resumable re-encryption migration; key-recovery runbook; move LLM credentials +to `contextual-orchestrator`; persisted non-secret credential metadata. + +**Status:** `in-progress`. + +--- + +## #947 โ€” Evidence-backed 3NF, FD, and hot-partition assessment (`[Product Gap]`) + +**Feature spec (summary).** A versioned Schema Quality & Operability +Assessment: normalization / functional-dependency findings from catalog + +profiling + declared-rule evidence (never a theorem from column names), with +`observed` / `declared` / `inferred` / `proposed` / `waived` evidence classes, +source refs, caveats, next actions, and signed waivers; hot-partition & growth +findings from workload evidence or an explicit capacity profile, with +`EXPLAIN` pruning fixtures; report as JSON + accessible HTML table + buyer +summary. + +**Current state.** `app.spec` has naming lint, wide-table, constraint, index, +FK-cycle analyzers. No normalization assessment; JSONB payloads are stored but +never described as 3NF proof. + +**Gap.** No defensible normalization / hot-partition answer for a buyer. + +**This loop's increment PRs.** +- **#1031** โ€” `app/spec/normalization_assessment.py`: catalog-evidence + analyzer. Findings: `non_atomic_column` (1NF), `missing_candidate_key` + (BCNF โ†’ insufficient_evidence), `nullable_unique_determinant` (BCNF), + `partial_dependency_precondition` (2NF). Evidence classes; waivers by scope. + 14 golden fixtures. +- **#1032** โ€” `app/spec/normalization_report.py` + `GET + /api/snapshots/{uuid}/normalization-assessment`: versioned report envelope + (stable SHA-256 fingerprint, generated_at, summary headline). IDOR-safe. +- **#1033** โ€” `app/spec/hot_partition_assessment.py` + `GET + /api/snapshots/{uuid}/hot-partition-assessment`: catalog + optional explicit + capacity profile. Findings: `append_heavy_table`, `unbounded_retention`, + `monotonic_key_hot_page`, `partition_semantics_review`, `skew_candidate`. + Concrete remediations only when a capacity profile supplies the quantity or + the signal is catalog-declared. 10 fixtures. +- **#1035** โ€” `app/spec/assessment_html.py` + `?format=html` on both + endpoints: accessible exact-value HTML (every cell `html.escape`d; + text-label state, not colour; `` per finding kind). Completes the + "JSON + HTML + summary" contract line. + +**Remaining increments.** 3NF / transitive-dependency detection (needs +profiling or declared FDs); persisted signed waiver records; the `EXPLAIN` +pruning fixtures against a real PostgreSQL; the versioned `assessment_run` +persistence; a Rust core once the #951 profile shows a measured hotspot. + +**Status:** `in-progress`. + +--- + +## #948 โ€” Snapshot promotion, bitemporal lineage, retention, recovery (`[Product Gap]`) + +**Feature spec (summary).** A first-class immutable lineage & promotion model: +separate `captured_at` / `available_at` / `valid_from` / `valid_to` / +`recorded_at` / `superseded_at` / `knowledge_cutoff`; typed parentโ†’child +derivations (`captured_from` / `imported_from` / `normalized_from` / +`compared_with` / `exported_from` / `planned_from`); optimistic-concurrency +promotion that closes intervals rather than rewriting; `development` / +`staging` / `production` environments; retention & legal hold as policy +records, not background deletes; recovery restores metadata + a diagram state +only (never a live DB). + +**Current state.** Immutable `schema_snapshot` / `schema_snapshot_data` + +`diff_snapshots`. A timestamped list, no lifecycle. + +**Gap.** No approved-baseline record, no derivation typing, no retention +policy, no recovery checkpoint. + +**This loop's increment PRs.** +- **#1038** โ€” `app/lineage/`: pure model + algorithms (no DB). `lineage_model` + bitemporal TypedDicts; `build_lineage_graph` (typed-edge DAG, cycle / + self-loop / unknown-kind rejection, topo order, orphans / dangling + reported); `apply_promotion` (append-only optimistic concurrency, closes + prior interval, `PromotionConflictError`); `decide_retention` (disposition + record, never deletes; promoted + legal-hold protected). 9 tests. + +**Remaining increments.** Normalized tables + Alembic migration; repositories ++ a `Settings`-gated HTTP surface (history / compare / promote / supersede / +archive / recover); PROV-JSON-LD projection; embed exact references into every +export. + +**Status:** `in-progress`. + +--- + +## #949 โ€” Governed forward-engineering apply, rollback, recovery (`[Product Epic]`) + +**Feature spec (summary, from title โ€” full re-read pending).** The +snapshot โ†’ DDL apply path must become *governed*: an approval gate before a +non-dry-run apply, a recorded plan / run / outcome, a rollback path, and a +recovery workflow distinct from metadata recovery. + +**Current state.** `app/ddl/apply_postgres_ddl` runs a validated +`ForwardDdlBatch` inside one transaction, `dry_run` default, SSRF-guarded. +`migration_safety.analyze_migration_safety` classifies risk. No approval +record, no run history, no rollback beyond the single-transaction rollback. + +**Gap.** No governance record, no multi-statement rollback strategy, no +recovery workflow. + +**This loop's increment PRs.** _none yet._ + +**Remaining increments.** A `migration_plan` / `migration_run` model (can +reuse the #948 lineage `planned_from` / `exported_from` edges and audit +records); an approval gate; a `pg_dump`-anchored recovery-point contract; +apply-time safety re-check against the live target. + +**Status:** `not-started` (adjacent to #948 lineage). + +--- + +## #950 โ€” GA deployment profiles, tenant isolation, SSO, provisioning (`[Enterprise Gap]`) + +**Feature spec (summary).** Two explicit, published profiles behind the same +contracts: `single_tenant_managed` (one org per deployment/database, external +OIDC / Keyverse with org binding, customer-owned backup/secret/network +policy, no cross-customer claim) and `multi_tenant_saas` (normalized tenant +authority tables; every persisted & cached object carries or derives an +immutable `tenant_account_uuid`; provisioning lifecycle with receipts; +per-tenant data-residency). Never imply multi-tenancy because projects have +members. + +**Current state.** Project membership, OIDC verification, API keys, encrypted +DSNs, share links. No tenant authority; no isolation-mode contract. + +**Gap.** No truthful deployment claim; no enforced tenant ownership. + +**This loop's increment PRs.** +- **#1039** โ€” `app/deploy/profile.py`: typed `DeploymentProfile` + + `validate_profile()` honesty validator (rejects a dishonest GA claim for + either profile), `AUTHORITY_BEARING_OBJECTS` enumeration, + `PROFILE_A_TEMPLATE` / `PROFILE_B_TEMPLATE`. 9 tests. + +**Remaining increments.** `tenant_account` authority tables + migration; a +repository layer deriving `tenant_account_uuid` on every authority-bearing +read/write + a test that no authority table lacks the column; SSO / SCIM +identity-link + provisioning flows; data-residency enforcement; a +`Settings`-selected active profile with a fail-closed startup self-check +running `validate_profile`. + +**Status:** `in-progress`. + +--- + +## #951 โ€” Large-schema SLOs, workload benchmarks, measured Rust boundary (`[Performance Gap]`) + +**Feature spec (summary).** A versioned Performance & Capacity Profile: +deterministic anonymized `small` / `medium` / `large` workload generators plus +skew cases; measured paths (capture, hashing, JSON encode/decode + persist, +diff, export, API, queue, browser); p50/p95/p99 + RSS + allocations + query +count + lock wait + queue lag + artifact size + cancellation time; SLOs +separated from benchmark targets, **no SLA until production evidence**; a Rust +decision gate ADR per measured hotspot. + +**Current state.** Focused perf work (background introspection, indexed queue +claims, bounded parsing, memoized search). No published capacity envelope. + +**Gap.** No reproducible workload model, no measured baseline, no Rust +decision evidence. + +**This loop's increment PRs.** +- **#1036** โ€” `app/perf/workload_profiles.py`: deterministic anonymized + generators hitting #951's exact counts for `small` / `medium` / `large`; + skew builders (5,000-col relation, dense FK cluster, deep chain, + disconnected components, multilingual/quoted identifiers + large comments, + partition hierarchy). Seeded โ†’ byte-identical. **No invented threshold** + (meta-test enforced). 12 tests; `large` in ~0.4s. + +**Remaining increments.** A `run_baseline(profile, paths) -> dict` measurement +harness (plumbing only, no thresholds); `docs/PERFORMANCE.md`; the +release-candidate benchmark workflow with a reproducibility receipt; frontend +traces; per-hotspot Rust decision-gate ADRs. + +**Status:** `in-progress`. + +--- + +## #952 โ€” Tenant-scoped document & LLM workflows without weakening standalone (`[Ecosystem Gap]`) + +**Feature spec (summary, from title โ€” full re-read pending).** The reversing +spec / data-dictionary / document workflows and the LLM draft path must be +tenant-scoped in the `multi_tenant_saas` profile while the `standalone` +profile keeps working with no network and no Keyverse. LLM access goes +through the `contextual-orchestrator` contract, not a per-provider key vault. + +**Current state.** `app/spec/llm.py` calls an OpenAI-compatible provider +directly via `LLM_API_BASE_URL` / `LLM_API_KEY` / `LLM_MODEL`; local-only +reversing spec works without it. No tenant scoping on document artifacts. + +**Gap.** LLM credentials are unmanaged (ties to #946); document artifacts are +not tenant-scoped (ties to #950); no `contextual-orchestrator` connector. + +**This loop's increment PRs.** _none yet_ (foundations in #1037 credential +boundary and #1039 tenant authority model). + +**Remaining increments.** A `contextual-orchestrator` client behind the #946 +provider boundary; tenant-scoping of reversing-spec / data-dictionary / +connector artifacts per #950; a `standalone` profile conformance test +(no network, no Keyverse). + +**Status:** `not-started` (blocked on #946 + #950 foundations). + +--- + +## #953 โ€” First commercial release with exact-head, migration, operability, supply-chain evidence (`[Release Epic]`) + +**Feature spec (summary, from title โ€” full re-read pending).** The umbrella +release gate: exact-current-head evidence for every claim, a rehearsed +migration path, an operability baseline (SLOs, dashboards, runbooks), and +supply-chain evidence (hash-locked deps, digest-pinned images, SBOM, +attestation). Consumes #946โ€“#952. + +**Current state.** Supply-chain pinning is already enforced (hash-locked pip, +digest-pinned Docker, SHA-pinned Actions, OpenSSF Scorecard). CI runs mypy + +pytest + typecheck + vitest + production build + CodeQL + Scorecard + +dependency-review. No consolidated release evidence manifest. + +**Gap.** No single release-evidence manifest; the operability baseline +(#951), tenant claim (#950), credential lifecycle (#946), lineage (#948), and +governed apply (#949) are all incomplete. + +**This loop's increment PRs.** This document is the first artifact toward the +#953 evidence manifest. Loop PRs #1024 (`.Jules` case-collision fix that +unblocks CI-clean git ops) and #1025 (local Playwright E2E harness + `nanoid` +pin, closes #1014) are release-hygiene prerequisites. + +**Remaining increments.** A release-evidence manifest generator; the +operability baseline; migration rehearsal automation; then a version bump + +`CHANGELOG` release section once #946โ€“#952 reach `merge-ready` on their MVP +increments. + +**Status:** `spec'd`. + +--- + +## Cross-repo / ecosystem + +| repo | relationship to pg-erd-cloud | status | +| --- | --- | --- | +| `ContextualWisdomLab/.github` | Central required-workflow authority (`opencode-review`, `strix`, coverage, scorecard). **Currently the commercial-readiness blocker** (`#1531`). | incident, owned by a parallel effort | +| `ContextualWisdomLab/keyverse` | Central Identity Provider โ€” the `keyverse` identity mode in #950; org binding for the single-tenant GA profile. | not yet integrated | +| `ContextualWisdomLab/contextual-orchestrator` | The LLM access contract #946 ยง9 and #952 require pg-erd-cloud to adopt instead of a per-provider key. | not yet integrated | +| `ContextualWisdomLab/wardnet` | Rust-first gateway / SOC control-plane baseline; relevant to #950 ingress + #953 operability. | not yet integrated | +| `ContextualWisdomLab/TEPP`, `fast-mlsirm` | Psychometrics platforms โ€” **not consumed by pg-erd-cloud**; listed for ecosystem completeness only. | n/a | +| `ContextualWisdomLab/RankWeave`, `ThreadWeave`, `LineageWeave`, `disksage` | Independent libraries; `LineageWeave`'s DAG-reconstruction idea informed the #948 lineage model shape but the code is not imported. | n/a | + +## How this document is maintained + +The autonomous review/merge loop updates this file each time a gap increment +ships or the incident status changes. When the gate clears and PR #942 +merges, reconcile its `docs/product-technical-gap-baseline.md`, +`docs/doctoring/product-technical-gap-baseline.md`, and +`docs/adr/0002-product-technical-gap-baseline.md` with this consolidation. From cb762cd720b808cbd32bd871a7270dcb957b6c79 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 1 Sep 2026 23:21:13 +0900 Subject: [PATCH 02/10] docs: fill #949/#952/#953 gap sections; address PR #1040 review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - #949: replace the placeholder with the issue's seven-part bounded decomposition (plan authority, sandbox runtime, live preflight provider, approval/authorization, apply worker, convergence/recovery, ops/evidence) and the mandatory safety invariants. - #952: replace the placeholder with the three governed vertical workflows (reference-document attachment, grounded reversing spec, naruon projection) and the product boundary. Reconcile the contextual- orchestrator wording with the existing configuration-only /chat/completions integration in docs/llm-orchestrator-integration.md (CodeRabbit finding) โ€” remaining work is governance (credential boundary, tenant context, discovery/routing/fallback delegation), not a missing transport. - #953: replace the placeholder with the release-integration scope (PR-queue shaping, dependency backlog with per-item decisions, required release evidence) and list #1040/#1024/#1025 as its increments. - #951: add #1041 (baseline harness) to the increment PRs; update the remaining increments. - Fix the stacked-PR count/list mismatch (Devin + CodeRabbit finding): 11 increment PRs + this document, with #942 called out separately. - Add a References (APA 7th) section (Devin "research grounding absent" finding): AERA/APA/NCME 2014, Codd 1971, NIST SP 800-218, SLSA v1.2, PostgreSQL 18 DDL. Docs-only; tests/test_docstrings.py green. Still blocked from merge by ContextualWisdomLab/.github#1531. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 367 ++++++++++++++++++++----- 2 files changed, 297 insertions(+), 72 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 676fb5dca..6c24441ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready PR 10๊ฑด ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1036/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€๋ฅผ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 11๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1036/#1041/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 1f6b0701f..3dabb5112 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product & technical gap baseline -**Last consolidated:** 2026-09-01 (autonomous review/merge loop, iter14). +**Last consolidated:** 2026-09-01 (autonomous review/merge loop, iter16). This document is the single tracker for the distance between what pg-erd-cloud does today and a defensible first commercial release. It is @@ -43,8 +43,15 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter14 the loop has 10 such PRs stacked -(#942, #1024, #1025, #1031, #1032, #1033, #1035, #1036, #1037, #1038, #1039). +the gate clears. As of iter16 the loop is holding **11 stacked increment +PRs** โ€” #1024, #1025, #1031, #1032, #1033, #1035, #1036, #1037, #1038, +#1039, #1041 โ€” plus **this document** (#1040). Separately, **#942** (the +original baseline draft) is green on every required check and waits only on +one non-author approval; it is not one of the 11 increments. + +Dependency order for the merge wave once the gate clears: #942 โ†’ #1024 โ†’ +#1025 โ†’ #1031 โ†’ #1032 โ†’ #1033 โ†’ #1035 โ†’ #1036 โ†’ #1041 โ†’ #1037 โ†’ #1038 โ†’ +#1039 โ†’ #1040. ## Status legend @@ -176,27 +183,85 @@ export. ## #949 โ€” Governed forward-engineering apply, rollback, recovery (`[Product Epic]`) -**Feature spec (summary, from title โ€” full re-read pending).** The -snapshot โ†’ DDL apply path must become *governed*: an approval gate before a -non-dry-run apply, a recorded plan / run / outcome, a rollback path, and a -recovery workflow distinct from metadata recovery. +**Feature spec (summary).** The snapshot โ†’ DDL path must become a +protected, versioned vertical workflow: base snapshot โ†’ proposed target โ†’ +deterministic migration plan โ†’ risk/precondition review โ†’ isolated dry run +โ†’ live read-only preflight โ†’ human approval โ†’ bounded apply โ†’ convergence +capture โ†’ success or recovery โ†’ immutable evidence bundle. The issue +mandates a **bounded-PR decomposition** rather than one growing branch: + +1. **Plan authority & compiler** โ€” immutable source/target snapshot IDs + + hashes; deterministic typed operations with dependency order; a + dialect/version capability matrix; reversible / conditionally reversible + / irreversible classification; fixed resource limits; no free-form SQL + authority. +2. **Sandbox runtime** โ€” ephemeral isolated PostgreSQL 14โ€“18 with no + production credentials or customer network; CPU/memory/storage/ + wall-clock/statement/output bounds; cleanup + orphan reaper; a + convergence report. +3. **Stored-target live preflight provider** โ€” exact project / connection / + base-snapshot / attempt-lease binding; post-connect revalidation; + read-only catalog capture + precondition checks; DNS/SSRF/TLS + least + privilege; secret-safe errors; cancellation. +4. **Approval & authorization** โ€” deployer role + maker-checker for + high-risk plans; exact plan digest / target fingerprint / environment / + expiry / scope; approval invalidated on any plan/target/state change; an + accessible review UI that explains risk and the next action. +5. **Apply worker** โ€” production consumer registration; one active attempt + per run with fenced leases + heartbeats; statement-level timeouts + + cancellation checkpoints; a transaction boundary declared per operation + class; retry only where idempotency is proved; no generic replay of + partially committed DDL. +6. **Convergence & recovery** โ€” recapture target state through the same + guarded connection; compare actual vs planned; distinguish success / + partial / divergent / unknown; generate recovery guidance from known + committed operations; integrate approved backup/PITR evidence; never + claim automatic rollback for irreversible or non-transactional DDL. +7. **Operations & evidence** โ€” durable event/outbox/inbox; OpenTelemetry + traces + metrics with no DSN/schema-value leakage; incident + + cancellation runbooks; downloadable signed execution evidence + + machine-readable provenance; recovery from restart / worker crash / + lease loss / queue duplication / provider timeout. + +**Safety invariants (must hold).** `dry_run=false` stays default-deny +until deployment policy explicitly enables the final apply capability; a +legacy free-form SQL route can never silently become structured apply +authority; the worker never accepts plaintext DSNs, connection overrides, +or plan SQL from queue payloads; every external identifier is re-resolved +and re-authorized at execution time; the target is sticky to the approved +provider/connection lineage; no status is `successful` before post-apply +convergence evidence is committed transactionally with the outbox event. **Current state.** `app/ddl/apply_postgres_ddl` runs a validated `ForwardDdlBatch` inside one transaction, `dry_run` default, SSRF-guarded. -`migration_safety.analyze_migration_safety` classifies risk. No approval -record, no run history, no rollback beyond the single-transaction rollback. - -**Gap.** No governance record, no multi-statement rollback strategy, no -recovery workflow. - -**This loop's increment PRs.** _none yet._ - -**Remaining increments.** A `migration_plan` / `migration_run` model (can -reuse the #948 lineage `planned_from` / `exported_from` edges and audit -records); an approval gate; a `pg_dump`-anchored recovery-point contract; -apply-time safety re-check against the live target. - -**Status:** `not-started` (adjacent to #948 lineage). +`migration_safety.analyze_migration_safety` classifies risk. PR #834 built +an execution-neutral foundation (structured plans, dry-run attempts, +cancellation, leases, live preflight, audit evidence) but deliberately +registers no production consumer, provisions no sandbox, grants no live +apply authority, and proves no process recovery. + +**Gap.** No production apply consumer; no sandbox runtime; no approval +record bound to an exact plan digest; no convergence/recovery step; no +immutable evidence bundle; #834's useful commits are not yet decomposed +onto protected `main`. + +**This loop's increment PRs.** _none yet_ โ€” deferred behind the #948 +lineage model (parts 1 and 6 reuse `planned_from` / `exported_from` edges +and audit records) and the #946 credential boundary (part 3 preflight +provider). Sequencing #948 โ†’ #946 integration โ†’ #949 part 1 avoids +building the plan model twice. + +**Remaining increments.** All seven parts above, each as a bounded PR from +protected `main` with exact-head evidence; realistic acceptance tests on +PostgreSQL 14โ€“18 (additive column/index/FK, rename, type conversion, +partition op, extension-owned index AM, quoted multilingual identifiers) +and failure injection (lock contention, statement timeout, deadlock, +connection loss, worker `SIGKILL`, lease expiry, duplicate signal, restart; +plan/target changed after approval; partial-commit recovery without +replay). + +**Status:** `spec'd` (foundations forming in #948 / #946; adjacent to #948 +lineage). --- @@ -256,11 +321,23 @@ decision evidence. disconnected components, multilingual/quoted identifiers + large comments, partition hierarchy). Seeded โ†’ byte-identical. **No invented threshold** (meta-test enforced). 12 tests; `large` in ~0.4s. - -**Remaining increments.** A `run_baseline(profile, paths) -> dict` measurement -harness (plumbing only, no thresholds); `docs/PERFORMANCE.md`; the -release-candidate benchmark workflow with a reproducibility receipt; frontend -traces; per-hotspot Rust decision-gate ADRs. +- **#1041** โ€” `app/perf/baseline.py` (stacked on #1036): + `run_baseline(profile_name, *, seed=None) -> dict` times the pure + side-effect-free paths โ€” canonical hash, JSON round-trip, self-diff, + PostgreSQL + Snowflake DDL export, data-dictionary Markdown โ€” and records + only `wall_seconds`, `tracemalloc` `peak_bytes`, and `result_size_bytes` + per path. `python -m app.perf.baseline --profile small [--seed N] + [--json]` CLI. `tracemalloc` torn down in `finally`; a cancelled run + returns no partial report. **No threshold or verdict** (meta-test + enforced). 9 tests. + +**Remaining increments.** Repeat-run percentile aggregation over +`run_baseline` (p50/p95/p99 + min/max per path, still threshold-free); the +DB / event-loop paths (API list/detail/pagination/search, queue +claim/retry/lease/cleanup/fairness) in the benchmark workflow; +`docs/PERFORMANCE.md`; the release-candidate benchmark workflow with a +reproducibility receipt; frontend traces; per-hotspot Rust decision-gate +ADRs. **Status:** `in-progress`. @@ -268,59 +345,172 @@ traces; per-hotspot Rust decision-gate ADRs. ## #952 โ€” Tenant-scoped document & LLM workflows without weakening standalone (`[Ecosystem Gap]`) -**Feature spec (summary, from title โ€” full re-read pending).** The reversing -spec / data-dictionary / document workflows and the LLM draft path must be -tenant-scoped in the `multi_tenant_saas` profile while the `standalone` -profile keeps working with no network and no Keyverse. LLM access goes -through the `contextual-orchestrator` contract, not a per-provider key vault. - -**Current state.** `app/spec/llm.py` calls an OpenAI-compatible provider -directly via `LLM_API_BASE_URL` / `LLM_API_KEY` / `LLM_MODEL`; local-only -reversing spec works without it. No tenant scoping on document artifacts. - -**Gap.** LLM credentials are unmanaged (ties to #946); document artifacts are -not tenant-scoped (ties to #950); no `contextual-orchestrator` connector. - -**This loop's increment PRs.** _none yet_ (foundations in #1037 credential -boundary and #1039 tenant authority model). - -**Remaining increments.** A `contextual-orchestrator` client behind the #946 -provider boundary; tenant-scoping of reversing-spec / data-dictionary / -connector artifacts per #950; a `standalone` profile conformance test -(no network, no Keyverse). - -**Status:** `not-started` (blocked on #946 + #950 foundations). +**Feature spec (summary).** Turn the currently-optional connector calls +into three complete, governed vertical workflows while keeping standalone +operation fully functional: + +1. **Reference-document attachment** โ€” project/snapshot/table โ†’ authorized + attachment intent โ†’ signed tenant/purpose request โ†’ Clearfolio + conversion job โ†’ durable connector receipt โ†’ viewer artifact reference โ†’ + project evidence drawer. Needs normalized `connector_account` / + `connector_grant` / `document_reference` / `attachment_binding` / + `connector_job` / `connector_receipt` metadata; opaque external IDs only; + short-lived signed tenant/project/purpose claims; an allowlisted + endpoint with exact host/port/method/MIME/timeout/size/redirect/retry + policy; consent + data-classification review; status/retry/cancel/ + revoke/expiry; immutable source hash; no document contents in any log, + metric, billing record, or LLM trace. +2. **Grounded reversing specification** โ€” exact snapshot + authorized + references โ†’ evidence bundle โ†’ orchestrator operation (e.g. + `draft_database_reversing_spec`) โ†’ schema-bound draft โ†’ independent + grounding verification โ†’ reviewed revision. Must send bounded semantic + evidence units (never whole documents or DSNs); record snapshot hash, + evidence IDs, model/provider IDs, prompt hash, orchestration mode, + reasoning effort, knowledge cutoff, and verification result; distinguish + local deterministic draft / LLM draft / verified draft / human-approved + revision; detect unsupported claims, wrong object names / cardinality, + inverted relationships, fabricated rationale, and prompt injection from + comments or documents; no automatic publication or migration approval. +3. **Naruon / context-fabric projection** โ€” a read-only versioned evidence + contract for authorized consumers: canonical references, truth status + (`observed` / `declared` / `inferred` / `proposed`), valid/system time + + knowledge cutoff, provenance + source hashes, policy-filtered metadata + with no DSN/secret, an idempotent event/receipt contract, and **no + requirement that naruon be present** for standalone operation. + +**Product boundary (explicit in the issue).** pg-erd-cloud stays the +authority for ERD projects, connections, snapshots, views, annotations, +sharing, migration plans/runs, and connector *references*. It does not +become a document viewer, object store, PIM/knowledge graph, or LLM +gateway. Clearfolio owns document conversion/viewer jobs; contextual- +orchestrator owns provider/model discovery, routing, fallback, +orchestration, evaluation, and cost/quality telemetry; naruon may consume +pg-erd-cloud evidence through an explicit connector but never owns project +state. Every integration is optional and fails as an *unavailable +capability*, not a broken core product. + +**Current state.** `app/spec/llm.py` already performs a **configuration- +only** OpenAI-compatible integration: it calls a `/chat/completions` +endpoint via `LLM_API_BASE_URL` / `LLM_API_KEY` / `LLM_MODEL` (see +`docs/llm-orchestrator-integration.md`) and the local deterministic +reversing spec / data dictionary work with no LLM configured. The +transport works; what is missing is governance, not a connection. + +**Gap.** The LLM credentials are unmanaged runtime config (ties to #946); +model discovery / capability routing / fallback / evaluation are not +delegated to `contextual-orchestrator` (the issue requires replacing +direct per-provider runtime authority with a versioned orchestrator +operation, and supporting non-chat-completions model classes such as +NVIDIA NIM via discovery + fallback); no tenant/purpose scoping or +evidence lineage on document artifacts (ties to #950); connector +failure / retry / revocation is not one coherent UI + audit contract; no +`standalone`-mode conformance test proving all connectors can be disabled. + +**This loop's increment PRs.** _none yet_ โ€” foundations in #1037 +(credential-provider boundary the orchestrator client sits behind) and +#1039 (tenant authority model the artifact scoping needs). + +**Remaining increments.** A versioned `contextual-orchestrator` client +behind the #946 provider boundary that replaces the direct +`LLM_API_*` runtime authority and adds discovery / capability routing / +fallback / grounding verification; the normalized connector-reference +metadata + Clearfolio attachment workflow; tenant-scoping of +reversing-spec / data-dictionary / connector artifacts per #950; the +naruon read-only evidence contract; a `standalone` profile conformance +test (no network, no Keyverse, all connectors disabled) plus adversarial +tests (cross-tenant attachment, credential revocation mid-job, webhook +replay/reorder, DNS-rebind / oversized body / wrong MIME, document + schema +comment prompt injection, fabricated table/column/FK in LLM output, +knowledge-cutoff leakage). + +**Status:** `spec'd` (transport exists; governance blocked on #946 + #950 +foundations). --- ## #953 โ€” First commercial release with exact-head, migration, operability, supply-chain evidence (`[Release Epic]`) -**Feature spec (summary, from title โ€” full re-read pending).** The umbrella -release gate: exact-current-head evidence for every claim, a rehearsed -migration path, an operability baseline (SLOs, dashboards, runbooks), and -supply-chain evidence (hash-locked deps, digest-pinned images, SBOM, -attestation). Consumes #946โ€“#952. - -**Current state.** Supply-chain pinning is already enforced (hash-locked pip, -digest-pinned Docker, SHA-pinned Actions, OpenSSF Scorecard). CI runs mypy + -pytest + typecheck + vitest + production build + CodeQL + Scorecard + -dependency-review. No consolidated release evidence manifest. +**Feature spec (summary).** Produce the first truthful, installable, +supportable **single-tenant managed / self-hosted GA candidate**. +Multi-tenant SaaS stays non-GA until #950 is complete; the release must +work standalone with optional CWL connectors as capability additions, not +hidden prerequisites. The epic **owns release integration only** and must +not duplicate implementation bodies. Its work: + +- **PR-queue shaping.** Capture the exact protected-`main` SHA, ruleset, + required checks, and every open PR's exact head. Classify each PR: + unique in-scope change / stack dependency / superseded-duplicate / + contaminated aggregate needing reconstruction / experiment-or-post-GA / + blocked by the org control-plane incident. Close duplicates with a link + to the canonical issue; never transfer stale-head review evidence. + Rebase bounded stacks in dependency order without force-pushing over + concurrent agent work. Refresh **this document** after each integration + wave. A release-cut branch/tag comes only from protected `main`. +- **Dependency backlog** (each gets an explicit `release_blocker` / + `post_ga_committed` / `experimental` / `not_planned` decision + rationale + before release): #946, #947, #948, #949, #950, #951, #952, #865 + (orphaned Actions identities), #899 / #928 / PR #944 (design-system / + Storybook contract), PR #936 / #838 (ORM โ†” Alembic exact-head drift). + Core security, data integrity, migration safety, standalone deployment, + backup/restore, operability, licensing, and supported-database + truthfulness cannot be deferred silently. +- **Required release evidence.** A clean-environment browser/API rehearsal + of the full product journey (login โ†’ project โ†’ encrypted connection โ†’ + async snapshot โ†’ ERD search/layout/annotation/saved view โ†’ diff/exports โ†’ + share + revocation โ†’ approved snapshot/history โ†’ backup and restore); + clean install on PostgreSQL 18 + the compatibility matrix; upgrade from + the oldest supported `0.1.x` through every Alembic revision + + downgrade/rollback policy; ORMโ†”migration drift producing no unreviewed + DDL; backup + PITR/logical restore + queue/job recovery after restart; + 100% production statement + branch + public-API docstring coverage with + real PostgreSQL fixtures; fuzz/property tests at the DSN / identifier / + snapshot / DBML-DDL / import-export / connector boundaries; threat model + + secure deployment guide + a CSAP / SOC 2 control **crosswalk** (an + engineering evidence map, not a certification claim); reproducible + backend/frontend/container builds; an SPDX or CycloneDX **SBOM** per + artifact; **SLSA v1.2**-compatible build provenance; container + FS vuln + results with reviewed exceptions; a signed tag/release + documented + rollback; an **immutable release manifest** (source commit, migrations, + dependency locks, workflow provenance, SBOM, image digest, test/benchmark + receipts, Figma file ID, known limitations); liveness/readiness split; + OpenTelemetry traces/metrics/logs with stable cardinality and no + secrets/customer values; SLI/SLO + capacity profile linked to #951; + dashboards/alerts + runbooks for secret loss/rotation, target outage, + queue backlog, failed migration, backup restore, dependency incident, + compromised share/API key. + +**Current state.** At `main@8dc74692` backend + frontend versions are +`0.1.0`; the repo has 60+ open PRs. Supply-chain pinning is already +enforced (hash-locked pip, digest-pinned Docker, SHA-pinned Actions, +OpenSSF Scorecard). CI runs mypy + pytest + typecheck + vitest + production +build + CodeQL + Scorecard + dependency-review. No tagged, +provenance-backed release candidate proves the complete buyer journey; no +consolidated release-evidence manifest exists. + +**Gap.** No single release-evidence manifest; no PR-queue classification of +record; the operability baseline (#951), tenant claim (#950), credential +lifecycle (#946), lineage (#948), and governed apply (#949) are all +incomplete; PR #834's useful commits are not yet decomposed onto `main`. -**Gap.** No single release-evidence manifest; the operability baseline -(#951), tenant claim (#950), credential lifecycle (#946), lineage (#948), and -governed apply (#949) are all incomplete. - -**This loop's increment PRs.** This document is the first artifact toward the -#953 evidence manifest. Loop PRs #1024 (`.Jules` case-collision fix that -unblocks CI-clean git ops) and #1025 (local Playwright E2E harness + `nanoid` -pin, closes #1014) are release-hygiene prerequisites. +**This loop's increment PRs.** +- **#1040** โ€” this document: the first artifact toward the #953 evidence + manifest and the PR-queue classification of record (every loop PR mapped + to its issue, the org-incident blocker named, the merge-wave dependency + order stated). +- **#1024** โ€” `.Jules` โ†” `.jules` case-collision fix that unblocks + CI-clean git operations on case-insensitive filesystems (release-hygiene + prerequisite for any rebase wave). +- **#1025** โ€” local Playwright E2E harness + `nanoid` pin (closes #1014); + the harness the product-journey rehearsal will extend. **Remaining increments.** A release-evidence manifest generator; the -operability baseline; migration rehearsal automation; then a version bump + -`CHANGELOG` release section once #946โ€“#952 reach `merge-ready` on their MVP -increments. +operability baseline; migration rehearsal automation; the per-dependency +release decision table; then a synchronized version bump + `CHANGELOG` +release section + `RELEASE_NOTES.md` once #946โ€“#952 reach `merge-ready` on +their MVP increments. -**Status:** `spec'd`. +**Status:** `spec'd` (this document + #1024 / #1025 are the first +release-hygiene increments). --- @@ -335,10 +525,45 @@ increments. | `ContextualWisdomLab/TEPP`, `fast-mlsirm` | Psychometrics platforms โ€” **not consumed by pg-erd-cloud**; listed for ecosystem completeness only. | n/a | | `ContextualWisdomLab/RankWeave`, `ThreadWeave`, `LineageWeave`, `disksage` | Independent libraries; `LineageWeave`'s DAG-reconstruction idea informed the #948 lineage model shape but the code is not imported. | n/a | +## References (APA 7th) + +The contracts summarized above lean on these external standards; each gap's +own doctoring note under `docs/doctoring/` carries the domain-specific +citations for its increment. + +- American Educational Research Association, American Psychological + Association, & National Council on Measurement in Education. (2014). + *Standards for educational and psychological testing*. American + Educational Research Association. โ€” evidence-class framing (`observed` / + `declared` / `inferred` / `proposed`) in #947, #948, #952. +- Codd, E. F. (1971). Further normalization of the data base relational + model. In R. Rustin (Ed.), *Data base systems* (Courant Computer Science + Symposia Series, Vol. 6). Prentice-Hall. โ€” normalization assessment in + #947. +- International Organization for Standardization. (2021). *Health + informatics โ€” Pseudonymization* (ISO/TS 25237-adjacent principle: + protection by access control, encryption, purpose limitation, and audit + rather than blanket masking). โ€” the non-masking protection stance in + #946, #949, #953. +- National Institute of Standards and Technology. (2022). *Secure software + development framework (SSDF) version 1.1* (NIST Special Publication + 800-218). https://doi.org/10.6028/NIST.SP.800-218 โ€” the release evidence + and governed-apply controls in #949 and #953. +- PostgreSQL Global Development Group. (2026). *PostgreSQL 18 documentation: + Data definition*. https://www.postgresql.org/docs/18/ddl.html โ€” the + supported-operation matrix in #949 and the compatibility matrix in #953. +- SLSA Community. (2025). *Supply-chain levels for software artifacts + specification, version 1.2*. https://slsa.dev/spec/v1.2/ โ€” the build + provenance and attestation requirements in #953. + ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes. When the gate clears and PR #942 +ships or the incident status changes (this revision: iter16 โ€” filled the +#949 / #952 / #953 sections from their issue bodies, added #1041, corrected +the stacked-PR count, and reconciled the #952 orchestrator wording with the +existing configuration-only `/chat/completions` integration in +`docs/llm-orchestrator-integration.md`). When the gate clears and PR #942 merges, reconcile its `docs/product-technical-gap-baseline.md`, `docs/doctoring/product-technical-gap-baseline.md`, and `docs/adr/0002-product-technical-gap-baseline.md` with this consolidation. From 8e02e741deeb1f0476156cd50f4f824bff3a85c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 01:32:44 +0900 Subject: [PATCH 03/10] docs: add #1045 to the #951 increment list; refresh stacked-PR count - #951 section: add #1045 (repeat-run percentile aggregation via app/perf/baseline_stats.py -- aggregate_baseline runs run_baseline N times over the same seed and reduces wall_seconds/peak_bytes to min/max/mean/p50/p95/p99 with stdlib statistics.quantiles, no threshold). Drop the percentile item from "Remaining increments". - Blocker section: 12 stacked increment PRs + this document; merge-wave order now #1036 -> #1041 -> #1045. - Maintenance note + "Last consolidated" date bumped to iter18 / 2026-09-02. Docs-only; tests/test_docstrings.py green. Still blocked from merge by ContextualWisdomLab/.github#1531. (PR #1040 post-cb762cd7 bot review not re-read this tick -- GitHub REST secondary rate limit on shared user 8172694; will check next tick.) Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 53 ++++++++++++++++---------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c24441ed..0d765818f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 11๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1036/#1041/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 12๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1036/#1041/#1045/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 3dabb5112..d8592d9a0 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product & technical gap baseline -**Last consolidated:** 2026-09-01 (autonomous review/merge loop, iter16). +**Last consolidated:** 2026-09-02 (autonomous review/merge loop, iter18). This document is the single tracker for the distance between what pg-erd-cloud does today and a defensible first commercial release. It is @@ -43,15 +43,15 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter16 the loop is holding **11 stacked increment -PRs** โ€” #1024, #1025, #1031, #1032, #1033, #1035, #1036, #1037, #1038, -#1039, #1041 โ€” plus **this document** (#1040). Separately, **#942** (the -original baseline draft) is green on every required check and waits only on -one non-author approval; it is not one of the 11 increments. +the gate clears. As of iter18 the loop is holding **12 stacked increment +PRs** โ€” #1024, #1025, #1031, #1032, #1033, #1035, #1036, #1041, #1045, +#1037, #1038, #1039 โ€” plus **this document** (#1040). Separately, **#942** +(the original baseline draft) is green on every required check and waits +only on one non-author approval; it is not one of the 12 increments. Dependency order for the merge wave once the gate clears: #942 โ†’ #1024 โ†’ -#1025 โ†’ #1031 โ†’ #1032 โ†’ #1033 โ†’ #1035 โ†’ #1036 โ†’ #1041 โ†’ #1037 โ†’ #1038 โ†’ -#1039 โ†’ #1040. +#1025 โ†’ #1031 โ†’ #1032 โ†’ #1033 โ†’ #1035 โ†’ #1036 โ†’ #1041 โ†’ #1045 โ†’ #1037 โ†’ +#1038 โ†’ #1039 โ†’ #1040. ## Status legend @@ -330,14 +330,23 @@ decision evidence. [--json]` CLI. `tracemalloc` torn down in `finally`; a cancelled run returns no partial report. **No threshold or verdict** (meta-test enforced). 9 tests. +- **#1045** โ€” `app/perf/baseline_stats.py` (stacked on #1041): + `aggregate_baseline(profile_name, *, repeat, seed=None) -> dict` runs + `run_baseline` `repeat` times over the *same* seeded workload (snapshot + fixed; only timing varies) and reduces each path's `wall_seconds` and + `peak_bytes` sample lists to `{samples, min, max, mean, p50, p95, p99}` + via `statistics.quantiles` (standard library only). `result_size_bytes` + is deterministic, so it stays a scalar. `repeat < 1` โ†’ `ValueError`; + `repeat == 1` โ†’ degenerate summary; a cancelled run returns no partial + aggregate. `python -m app.perf.baseline_stats --profile small --repeat 5 + [--seed N] [--json]` CLI. **No threshold or verdict** (meta-test + enforced). 9 tests. -**Remaining increments.** Repeat-run percentile aggregation over -`run_baseline` (p50/p95/p99 + min/max per path, still threshold-free); the -DB / event-loop paths (API list/detail/pagination/search, queue -claim/retry/lease/cleanup/fairness) in the benchmark workflow; -`docs/PERFORMANCE.md`; the release-candidate benchmark workflow with a -reproducibility receipt; frontend traces; per-hotspot Rust decision-gate -ADRs. +**Remaining increments.** The DB / event-loop paths (API +list/detail/pagination/search, queue claim/retry/lease/cleanup/fairness) in +the benchmark workflow; `docs/PERFORMANCE.md`; the release-candidate +benchmark workflow with a reproducibility receipt; frontend traces; +per-hotspot Rust decision-gate ADRs. **Status:** `in-progress`. @@ -559,11 +568,13 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes (this revision: iter16 โ€” filled the -#949 / #952 / #953 sections from their issue bodies, added #1041, corrected -the stacked-PR count, and reconciled the #952 orchestrator wording with the -existing configuration-only `/chat/completions` integration in -`docs/llm-orchestrator-integration.md`). When the gate clears and PR #942 -merges, reconcile its `docs/product-technical-gap-baseline.md`, +ships or the incident status changes (this revision: iter18 โ€” added #1045 +(repeat-run percentile aggregation) to the #951 increment list, updated the +stacked-PR count to 12, and refreshed the merge-wave order. iter16 filled +the #949 / #952 / #953 sections from their issue bodies and reconciled the +#952 orchestrator wording with the existing configuration-only +`/chat/completions` integration in `docs/llm-orchestrator-integration.md`). +When the gate clears and PR #942 merges, reconcile its +`docs/product-technical-gap-baseline.md`, `docs/doctoring/product-technical-gap-baseline.md`, and `docs/adr/0002-product-technical-gap-baseline.md` with this consolidation. From 45dce59c15903ccf219abee142ac13b5b5f11349 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 02:39:43 +0900 Subject: [PATCH 04/10] docs: address PR #1040 review round 3 (markdownlint, links, date, scope) - MD018: no prose line now starts with a bare #; the merge-wave order moved into a fenced text block (CodeRabbit). - Reference links: added the AERA/APA/NCME 2014 publisher page, the ISO/TS 25237:2017 catalogue link, and switched the normalization anchor to Codd (1970) CACM with a DOI (Devin "research grounding" / CodeRabbit "links or PDFs"). - "Last consolidated" set to 2026-09-01 UTC so it is not a future date relative to CI/reviewers (CodeRabbit). - #953 section: state explicitly that this document classifies only the loop's own increments and that the full ~60-open-PR classification table is a not-yet-done #953 deliverable, deferred until the merge wave drains the stack (Devin "queue classification remains partial"). - Skipped the 13:09-13:12 findings (PR-count mismatch, orchestrator wording) -- already fixed in cb762cd7. Docs-only; tests/test_docstrings.py green. Still blocked from merge by ContextualWisdomLab/.github#1531. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- docs/product-technical-gap-baseline.md | 89 ++++++++++++++++---------- 1 file changed, 55 insertions(+), 34 deletions(-) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index d8592d9a0..ceb12e5f9 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product & technical gap baseline -**Last consolidated:** 2026-09-02 (autonomous review/merge loop, iter18). +**Last consolidated:** 2026-09-01 UTC (autonomous review/merge loop, iter19). This document is the single tracker for the distance between what pg-erd-cloud does today and a defensible first commercial release. It is @@ -44,14 +44,20 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until the gate clears. As of iter18 the loop is holding **12 stacked increment -PRs** โ€” #1024, #1025, #1031, #1032, #1033, #1035, #1036, #1041, #1045, -#1037, #1038, #1039 โ€” plus **this document** (#1040). Separately, **#942** -(the original baseline draft) is green on every required check and waits -only on one non-author approval; it is not one of the 12 increments. +PRs** plus **this document** (PR #1040). Separately, PR #942 (the original +baseline draft) is green on every required check and waits only on one +non-author approval; it is not one of the 12 increments. -Dependency order for the merge wave once the gate clears: #942 โ†’ #1024 โ†’ -#1025 โ†’ #1031 โ†’ #1032 โ†’ #1033 โ†’ #1035 โ†’ #1036 โ†’ #1041 โ†’ #1045 โ†’ #1037 โ†’ -#1038 โ†’ #1039 โ†’ #1040. +The 12 increments and the merge-wave order once the gate clears: + +```text +#942 (approval-pending, not an increment) + -> #1024 -> #1025 + -> #1031 -> #1032 -> #1033 -> #1035 (#947 chain) + -> #1036 -> #1041 -> #1045 (#951 chain) + -> #1037 (#946) -> #1038 (#948) -> #1039 (#950) + -> #1040 (this document) +``` ## Status legend @@ -415,9 +421,9 @@ evidence lineage on document artifacts (ties to #950); connector failure / retry / revocation is not one coherent UI + audit contract; no `standalone`-mode conformance test proving all connectors can be disabled. -**This loop's increment PRs.** _none yet_ โ€” foundations in #1037 -(credential-provider boundary the orchestrator client sits behind) and -#1039 (tenant authority model the artifact scoping needs). +**This loop's increment PRs.** _none yet_. Foundations are in PR #1037 (the +credential-provider boundary the orchestrator client sits behind) and in +PR #1039 (the tenant authority model the artifact scoping needs). **Remaining increments.** A versioned `contextual-orchestrator` client behind the #946 provider boundary that replaces the direct @@ -503,18 +509,27 @@ incomplete; PR #834's useful commits are not yet decomposed onto `main`. **This loop's increment PRs.** - **#1040** โ€” this document: the first artifact toward the #953 evidence - manifest and the PR-queue classification of record (every loop PR mapped - to its issue, the org-incident blocker named, the merge-wave dependency - order stated). + manifest. It currently classifies only **this loop's own increment + PRs** (each mapped to its issue, with the org-incident blocker named and + the merge-wave dependency order stated). The full #953 PR-queue shaping + step โ€” every one of the ~60 open PRs captured at its exact head and + classified as unique / stack-dependency / superseded-duplicate / + contaminated-aggregate / experiment-or-post-GA / blocked-by-incident โ€” + is **not yet done** and remains a tracked #953 deliverable (see + "Remaining increments"). - **#1024** โ€” `.Jules` โ†” `.jules` case-collision fix that unblocks CI-clean git operations on case-insensitive filesystems (release-hygiene prerequisite for any rebase wave). - **#1025** โ€” local Playwright E2E harness + `nanoid` pin (closes #1014); the harness the product-journey rehearsal will extend. -**Remaining increments.** A release-evidence manifest generator; the -operability baseline; migration rehearsal automation; the per-dependency -release decision table; then a synchronized version bump + `CHANGELOG` +**Remaining increments.** The full open-PR classification table (every +open PR at its exact head, with a `release_blocker` / `post_ga_committed` +/ `experimental` / `not_planned` decision + rationale) โ€” deferred until +the incident clears and the merge wave drains the loop's own stack, since +classifying ~60 PRs that cannot merge yet would go stale immediately; a +release-evidence manifest generator; the operability baseline; migration +rehearsal automation; then a synchronized version bump + `CHANGELOG` release section + `RELEASE_NOTES.md` once #946โ€“#952 reach `merge-ready` on their MVP increments. @@ -543,17 +558,21 @@ citations for its increment. - American Educational Research Association, American Psychological Association, & National Council on Measurement in Education. (2014). *Standards for educational and psychological testing*. American - Educational Research Association. โ€” evidence-class framing (`observed` / - `declared` / `inferred` / `proposed`) in #947, #948, #952. -- Codd, E. F. (1971). Further normalization of the data base relational - model. In R. Rustin (Ed.), *Data base systems* (Courant Computer Science - Symposia Series, Vol. 6). Prentice-Hall. โ€” normalization assessment in - #947. -- International Organization for Standardization. (2021). *Health - informatics โ€” Pseudonymization* (ISO/TS 25237-adjacent principle: - protection by access control, encryption, purpose limitation, and audit - rather than blanket masking). โ€” the non-masking protection stance in - #946, #949, #953. + Educational Research Association. + https://www.aera.net/Publications/Books/Standards-for-Educational-Psychological-Testing-2014-Edition + โ€” evidence-class framing (`observed` / `declared` / `inferred` / + `proposed`) in #947, #948, #952. +- Codd, E. F. (1970). A relational model of data for large shared data + banks. *Communications of the ACM, 13*(6), 377โ€“387. + https://doi.org/10.1145/362384.362685 โ€” the relational-normalization + basis (further normal forms follow in Codd, 1971/1972); normalization + assessment in #947. +- International Organization for Standardization. (2017). *Health + informatics โ€” Pseudonymization* (ISO/TS 25237:2017). + https://www.iso.org/standard/63553.html โ€” cited for the principle that + protection is access control, encryption, purpose limitation, and audit + rather than blanket masking; the non-masking protection stance in #946, + #949, #953. - National Institute of Standards and Technology. (2022). *Secure software development framework (SSDF) version 1.1* (NIST Special Publication 800-218). https://doi.org/10.6028/NIST.SP.800-218 โ€” the release evidence @@ -568,12 +587,14 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes (this revision: iter18 โ€” added #1045 -(repeat-run percentile aggregation) to the #951 increment list, updated the -stacked-PR count to 12, and refreshed the merge-wave order. iter16 filled -the #949 / #952 / #953 sections from their issue bodies and reconciled the -#952 orchestrator wording with the existing configuration-only -`/chat/completions` integration in `docs/llm-orchestrator-integration.md`). +ships or the incident status changes (this revision: iter19 โ€” fixed the +markdownlint MD018 line-start warnings and the reference links flagged on +PR #1040. iter18 added PR #1045 (repeat-run percentile aggregation) to the +performance-gap increment list, took the stacked-PR count to 12, and +refreshed the merge-wave order. iter16 filled the #949 / #952 / #953 +sections from their issue bodies and aligned the #952 orchestrator wording +with the existing configuration-only `/chat/completions` integration in +`docs/llm-orchestrator-integration.md`). When the gate clears and PR #942 merges, reconcile its `docs/product-technical-gap-baseline.md`, `docs/doctoring/product-technical-gap-baseline.md`, and From 2c30484c5dfc62612f7d9d26c2fd6a9dcab0b5cb Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 03:49:03 +0900 Subject: [PATCH 05/10] docs: add #1048 (transitive-dependency / 3NF assessment) to the #947 list - #947 section: #1048 bullet -- assess_transitive_dependencies, the 3NF layer. Catalog-only non_key_reference_cluster is a structural precondition (inferred); a caller-declared FD raises transitive_dependency_via_declared_fd (declared) paired with a candidate_3nf_split proposal (proposed); FDs are never inferred from names. "Remaining increments" now scopes the open work to row-level FD discovery from table data (a profiling service). - Blocker section: 13 stacked increment PRs; merge-wave #947 chain line is now #1031 -> #1032 -> #1033 -> #1035 -> #1048. - Maintenance note + "Last consolidated" -> iter20. MD018-clean. Docs-only; tests/test_docstrings.py green. No new PR #1040 bot review since 45dce59c (org review queue stuck). Still blocked from merge by ContextualWisdomLab/.github#1531. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 52 ++++++++++++++++---------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d765818f..9fc909995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 12๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1036/#1041/#1045/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 13๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index ceb12e5f9..86984ea4b 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product & technical gap baseline -**Last consolidated:** 2026-09-01 UTC (autonomous review/merge loop, iter19). +**Last consolidated:** 2026-09-01 UTC (autonomous review/merge loop, iter20). This document is the single tracker for the distance between what pg-erd-cloud does today and a defensible first commercial release. It is @@ -43,18 +43,18 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter18 the loop is holding **12 stacked increment +the gate clears. As of iter20 the loop is holding **13 stacked increment PRs** plus **this document** (PR #1040). Separately, PR #942 (the original baseline draft) is green on every required check and waits only on one -non-author approval; it is not one of the 12 increments. +non-author approval; it is not one of the 13 increments. -The 12 increments and the merge-wave order once the gate clears: +The 13 increments and the merge-wave order once the gate clears: ```text #942 (approval-pending, not an increment) -> #1024 -> #1025 - -> #1031 -> #1032 -> #1033 -> #1035 (#947 chain) - -> #1036 -> #1041 -> #1045 (#951 chain) + -> #1031 -> #1032 -> #1033 -> #1035 -> #1048 (#947 chain) + -> #1036 -> #1041 -> #1045 (#951 chain) -> #1037 (#946) -> #1038 (#948) -> #1039 (#950) -> #1040 (this document) ``` @@ -142,11 +142,24 @@ never described as 3NF proof. endpoints: accessible exact-value HTML (every cell `html.escape`d; text-label state, not colour; `
` per finding kind). Completes the "JSON + HTML + summary" contract line. - -**Remaining increments.** 3NF / transitive-dependency detection (needs -profiling or declared FDs); persisted signed waiver records; the `EXPLAIN` -pruning fixtures against a real PostgreSQL; the versioned `assessment_run` -persistence; a Rust core once the #951 profile shows a measured hotspot. +- **#1048** โ€” `app/spec/transitive_dependency_assessment.py` + (`assess_transitive_dependencies`): the third-normal-form layer. From the + catalog alone it can only flag `non_key_reference_cluster` โ€” more than + one non-candidate-key foreign-key column beside non-prime descriptive + columns โ€” as a *structural precondition* (evidence class `inferred`, + with a caveat that profiling or a declared FD is needed). Given a + caller-supplied `declared_functional_dependencies` list it asserts a real + 3NF violation as `transitive_dependency_via_declared_fd` (evidence class + `declared`) and pairs it with a `candidate_3nf_split` proposal (evidence + class `proposed`, never applied). It never infers a dependency from + column names; unresolvable declared FDs are returned, not dropped. + 13 golden fixtures. + +**Remaining increments.** Row-level functional-dependency *discovery* from +table data (a profiling service, out of scope for the pure analyzer); +persisted signed waiver records; the `EXPLAIN` pruning fixtures against a +real PostgreSQL; the versioned `assessment_run` persistence; a Rust core +once the #951 profile shows a measured hotspot. **Status:** `in-progress`. @@ -587,14 +600,15 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes (this revision: iter19 โ€” fixed the -markdownlint MD018 line-start warnings and the reference links flagged on -PR #1040. iter18 added PR #1045 (repeat-run percentile aggregation) to the -performance-gap increment list, took the stacked-PR count to 12, and -refreshed the merge-wave order. iter16 filled the #949 / #952 / #953 -sections from their issue bodies and aligned the #952 orchestrator wording -with the existing configuration-only `/chat/completions` integration in -`docs/llm-orchestrator-integration.md`). +ships or the incident status changes. This revision (iter20) added PR #1048 +(transitive-dependency / 3NF assessment) to the #947 list, took the +stacked-PR count to 13, and inserted it into the merge-wave order. iter19 +fixed the markdownlint MD018 line-start warnings and the reference links +flagged on PR #1040. iter18 added PR #1045 (repeat-run percentile +aggregation) to the performance-gap increment list. iter16 filled the three +epic sections (#949, #952, #953) from their issue bodies and aligned the +LLM-orchestrator wording with the existing configuration-only +`/chat/completions` integration in `docs/llm-orchestrator-integration.md`. When the gate clears and PR #942 merges, reconcile its `docs/product-technical-gap-baseline.md`, `docs/doctoring/product-technical-gap-baseline.md`, and From 430082c145f2cfa65910269c3e63e9c665cf53c9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 06:03:17 +0900 Subject: [PATCH 06/10] docs: add #1049 (#950) and #1050 (#948) to the increment lists - #948 section: #1050 bullet -- app/lineage/prov_projection.py to_prov_document, the pure W3C PROV-JSON projection of build_lineage_graph (entity per snapshot id incl. dangling parents, wasDerivedFrom per typed edge with pg:derivationKind, no new dependency). "Remaining increments" -> the PROV activity layer replaces the "PROV-JSON-LD projection" item. - #950 section: #1049 bullet -- app/deploy/tenant_authority_check.py check_tenant_authority, the concrete check behind all_authority_objects_tenant_scoped. "Remaining increments" now folds the check into the Settings startup self-check and the repository-layer test. - Blocker section: 15 stacked increment PRs; fenced merge-wave block adds #1038 -> #1050 and #1039 -> #1049. - Maintenance note + "Last consolidated" -> iter22. MD018-clean. Docs-only; tests/test_docstrings.py green. No new PR #1040 bot review since 2c30484c (org review queue stuck; .github queue 1057). Still blocked from merge by ContextualWisdomLab/.github#1531. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 61 +++++++++++++++++--------- 2 files changed, 41 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fc909995..7dbb31fff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 13๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1037/#1038/#1039)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 15๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1037/#1038/#1050/#1039/#1049)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 86984ea4b..5700e1d1b 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product & technical gap baseline -**Last consolidated:** 2026-09-01 UTC (autonomous review/merge loop, iter20). +**Last consolidated:** 2026-09-01 UTC (autonomous review/merge loop, iter22). This document is the single tracker for the distance between what pg-erd-cloud does today and a defensible first commercial release. It is @@ -43,19 +43,21 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter20 the loop is holding **13 stacked increment +the gate clears. As of iter22 the loop is holding **15 stacked increment PRs** plus **this document** (PR #1040). Separately, PR #942 (the original baseline draft) is green on every required check and waits only on one -non-author approval; it is not one of the 13 increments. +non-author approval; it is not one of the 15 increments. -The 13 increments and the merge-wave order once the gate clears: +The 15 increments and the merge-wave order once the gate clears: ```text #942 (approval-pending, not an increment) -> #1024 -> #1025 - -> #1031 -> #1032 -> #1033 -> #1035 -> #1048 (#947 chain) - -> #1036 -> #1041 -> #1045 (#951 chain) - -> #1037 (#946) -> #1038 (#948) -> #1039 (#950) + -> #1031 -> #1032 -> #1033 -> #1035 -> #1048 (#947 chain) + -> #1036 -> #1041 -> #1045 (#951 chain) + -> #1037 (#946) + -> #1038 (#948) -> #1050 + -> #1039 (#950) -> #1049 -> #1040 (this document) ``` @@ -190,11 +192,18 @@ policy, no recovery checkpoint. reported); `apply_promotion` (append-only optimistic concurrency, closes prior interval, `PromotionConflictError`); `decide_retention` (disposition record, never deletes; promoted + legal-hold protected). 9 tests. +- **#1050** โ€” `app/lineage/prov_projection.py` (`to_prov_document`): a pure + W3C **PROV-JSON** projection of the `build_lineage_graph` result. One + `prov:Entity` per snapshot id (including ids referenced only as a dangling + parent); one `wasDerivedFrom` per typed edge, carrying `pg:derivationKind` + so the "by kind" information survives. PROV-JSON is plain JSON, so no new + dependency; deterministic and `json.dumps`-serializable. 9 tests. **Remaining increments.** Normalized tables + Alembic migration; repositories + a `Settings`-gated HTTP surface (history / compare / promote / supersede / -archive / recover); PROV-JSON-LD projection; embed exact references into every -export. +archive / recover); a `wasGeneratedBy` / `activity` layer on the PROV +projection once the persisted model records the tool / commit / policy per +snapshot; embed exact references into every export. **Status:** `in-progress`. @@ -305,13 +314,21 @@ DSNs, share links. No tenant authority; no isolation-mode contract. `validate_profile()` honesty validator (rejects a dishonest GA claim for either profile), `AUTHORITY_BEARING_OBJECTS` enumeration, `PROFILE_A_TEMPLATE` / `PROFILE_B_TEMPLATE`. 9 tests. +- **#1049** โ€” `app/deploy/tenant_authority_check.py` (`check_tenant_authority`): + the concrete check behind the `all_authority_objects_tenant_scoped` bool. + Given `{name, columns, derives_tenant_from}` table descriptions it + partitions every `AUTHORITY_BEARING_OBJECTS` entry into `carrying` (has + `tenant_account_uuid`) / `derived` (scoped through a named parent) / + `missing_scoping` / `missing_definition`, and is `compliant` only when + neither missing-list has an entry. `single_org_per_database` returns + `applicable=False` / `compliant=True` with a reason. Pure; 11 tests. **Remaining increments.** `tenant_account` authority tables + migration; a repository layer deriving `tenant_account_uuid` on every authority-bearing -read/write + a test that no authority table lacks the column; SSO / SCIM -identity-link + provisioning flows; data-residency enforcement; a +read/write, feeding the real ORM metadata to `check_tenant_authority`; SSO / +SCIM identity-link + provisioning flows; data-residency enforcement; a `Settings`-selected active profile with a fail-closed startup self-check -running `validate_profile`. +running `validate_profile` and `check_tenant_authority`. **Status:** `in-progress`. @@ -600,15 +617,17 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes. This revision (iter20) added PR #1048 -(transitive-dependency / 3NF assessment) to the #947 list, took the -stacked-PR count to 13, and inserted it into the merge-wave order. iter19 -fixed the markdownlint MD018 line-start warnings and the reference links -flagged on PR #1040. iter18 added PR #1045 (repeat-run percentile -aggregation) to the performance-gap increment list. iter16 filled the three -epic sections (#949, #952, #953) from their issue bodies and aligned the -LLM-orchestrator wording with the existing configuration-only -`/chat/completions` integration in `docs/llm-orchestrator-integration.md`. +ships or the incident status changes. This revision (iter22) added PR #1049 +(the tenant-authority column-presence check) to the #950 list and PR #1050 +(the lineage PROV-JSON projection) to the #948 list, taking the stacked-PR +count to 15. iter20 added PR #1048 (transitive-dependency / 3NF assessment) +to the #947 list. iter19 fixed the markdownlint MD018 line-start warnings +and the reference links flagged on PR #1040. iter18 added PR #1045 +(repeat-run percentile aggregation) to the performance-gap increment list. +iter16 filled the three epic sections (#949, #952, #953) from their issue +bodies and aligned the LLM-orchestrator wording with the existing +configuration-only `/chat/completions` integration in +`docs/llm-orchestrator-integration.md`. When the gate clears and PR #942 merges, reconcile its `docs/product-technical-gap-baseline.md`, `docs/doctoring/product-technical-gap-baseline.md`, and From 4609d0318725521c3ee14786de1691c7915313a5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 12:29:54 +0900 Subject: [PATCH 07/10] docs: add #1056 (#951) and backfill #1051 (#946) to the increment lists - #951 section: #1056 bullet -- app/perf/baseline_report.py build_baseline_report, a versioned buyer-facing envelope around aggregate_baseline (report_version / generated_at / schema_fingerprint / summary with names+counts only / verbatim statistics). Mirrors the #1032 normalization-report envelope. "Remaining increments" trimmed. - #946 section: backfill the #1051 bullet (the pure APP_SECRET dual-read/single-write rotation core -- dual_read_decrypt + plan_key_rotation, needs_key_recovery for undecryptable rows) which was shipped at iter22 but not recorded here. "Remaining increments" now separates the pure core (done) from the DB migration job (needs a PG fixture). - Blocker section: 16 stacked increment PRs; fenced merge-wave block adds #1045 -> #1056 and #1037 -> #1051. - Maintenance note + "Last consolidated" -> iter28 / 2026-09-02 UTC. MD018-clean. Docs-only; tests/test_docstrings.py green. .github queue ~1417 (still rising). Still blocked from merge by ContextualWisdomLab/.github#1531. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 57 ++++++++++++++++++-------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dbb31fff..7c73a0e95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 15๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1037/#1038/#1050/#1039/#1049)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 16๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 5700e1d1b..be1124c51 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,6 +1,6 @@ # Product & technical gap baseline -**Last consolidated:** 2026-09-01 UTC (autonomous review/merge loop, iter22). +**Last consolidated:** 2026-09-02 UTC (autonomous review/merge loop, iter28). This document is the single tracker for the distance between what pg-erd-cloud does today and a defensible first commercial release. It is @@ -43,19 +43,19 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter22 the loop is holding **15 stacked increment +the gate clears. As of iter28 the loop is holding **16 stacked increment PRs** plus **this document** (PR #1040). Separately, PR #942 (the original baseline draft) is green on every required check and waits only on one -non-author approval; it is not one of the 15 increments. +non-author approval; it is not one of the 16 increments. -The 15 increments and the merge-wave order once the gate clears: +The 16 increments and the merge-wave order once the gate clears: ```text #942 (approval-pending, not an increment) -> #1024 -> #1025 -> #1031 -> #1032 -> #1033 -> #1035 -> #1048 (#947 chain) - -> #1036 -> #1041 -> #1045 (#951 chain) - -> #1037 (#946) + -> #1036 -> #1041 -> #1045 -> #1056 (#951 chain) + -> #1037 (#946) -> #1051 -> #1038 (#948) -> #1050 -> #1039 (#950) -> #1049 -> #1040 (this document) @@ -97,12 +97,23 @@ attribution. `LocalMountedFileProvider` (fail-closed on missing/empty/oversized/non-UTF8/ symlink/path-escape/non-file), `DeterministicTestProvider`. 14 tests incl. "value never appears in str/repr/format/logs". Rotation design documented. +- **#1051** โ€” `app/secret_provider/rotation.py` (stacked on #1037): the pure + core of the `APP_SECRET` dual-read / single-write rotation. `dual_read_decrypt` + tries each candidate `APP_SECRET` in order (HKDF key, then the legacy + raw-SHA-256 key, matching `app/security`); `plan_key_rotation` re-encrypts + rows that decrypt with a previous key under the active key, leaves + active-key rows alone, and surfaces undecryptable / malformed rows as + `needs_key_recovery` โ€” never dropped, never re-encrypted from a guess. No + DB, no `Settings`, no plaintext in the result. A round-trip test through + `app.security.encrypt_text` / `decrypt_text` guards the key derivation. 10 tests. **Remaining increments.** `Settings` integration behind a `local_secret_file` -profile; org credential-registry provider with cache-TTL + fail-closed -timeout/permission/revoked/stale; implement `APP_SECRET` dual-read rotation + -resumable re-encryption migration; key-recovery runbook; move LLM credentials -to `contextual-orchestrator`; persisted non-secret credential metadata. +profile; the `SecretReference`-backed key set wired into `app/security`; org +credential-registry provider with cache-TTL + fail-closed +timeout/permission/revoked/stale; the resumable re-encryption *migration job* +over `db_connection` rows (needs a DB + PG fixture); key-recovery runbook; +move LLM credentials to `contextual-orchestrator`; persisted non-secret +credential metadata. **Status:** `in-progress`. @@ -377,11 +388,20 @@ decision evidence. aggregate. `python -m app.perf.baseline_stats --profile small --repeat 5 [--seed N] [--json]` CLI. **No threshold or verdict** (meta-test enforced). 9 tests. - -**Remaining increments.** The DB / event-loop paths (API +- **#1056** โ€” `app/perf/baseline_report.py` (stacked on #1045): + `build_baseline_report(profile_name, *, repeat, seed=None) -> dict` wraps + `aggregate_baseline` in a versioned buyer-facing envelope โ€” `report_version`, + `generated_at` (UTC ISO-8601), a `schema_fingerprint` (`"sha256:"` digest + of the exact workload snapshot that was measured), and a `summary` + (`{headline, path_count, slowest_path_by_wall_p95}` โ€” names and counts + only, never a duration value). The full statistics block is preserved + verbatim under `statistics`. Mirrors the #1032 normalization-report + envelope pattern. **No threshold or verdict** (meta-test enforced). 8 tests. + +**Remaining increments.** The DB / event-loop measured paths (API list/detail/pagination/search, queue claim/retry/lease/cleanup/fairness) in the benchmark workflow; `docs/PERFORMANCE.md`; the release-candidate -benchmark workflow with a reproducibility receipt; frontend traces; +benchmark CI workflow with a reproducibility receipt; frontend traces; per-hotspot Rust decision-gate ADRs. **Status:** `in-progress`. @@ -617,11 +637,12 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes. This revision (iter22) added PR #1049 -(the tenant-authority column-presence check) to the #950 list and PR #1050 -(the lineage PROV-JSON projection) to the #948 list, taking the stacked-PR -count to 15. iter20 added PR #1048 (transitive-dependency / 3NF assessment) -to the #947 list. iter19 fixed the markdownlint MD018 line-start warnings +ships or the incident status changes. This revision (iter28) added PR #1056 +(the versioned baseline-report envelope) to the #951 list, taking the +stacked-PR count to 16. iter22 added PR #1049 (the tenant-authority +column-presence check) to the #950 list and PR #1050 (the lineage PROV-JSON +projection) to the #948 list. iter20 added PR #1048 (transitive-dependency / +3NF assessment) to the #947 list. iter19 fixed the markdownlint MD018 line-start warnings and the reference links flagged on PR #1040. iter18 added PR #1045 (repeat-run percentile aggregation) to the performance-gap increment list. iter16 filled the three epic sections (#949, #952, #953) from their issue From 853d1b0642687556ca525302e12be572092aba13 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 16:49:09 +0900 Subject: [PATCH 08/10] docs: add #1057 (#953 release-manifest assembler) to the increment lists Gate still frozen (main@8dc74692; .github#1531 queue ~1822, rising). iter32 gap-baseline consolidation: record PR #1057 (pure build_release_manifest assembler, new app/release/ package) as the #953 release-evidence increment. Stacked-PR count 16 -> 17; merge-wave block gains a #1057 (#953) line before #1040; #953 "Remaining increments" trimmed to SBOM / signed provenance / operability baseline / migration rehearsal / per-dependency decision table / open-PR classification-of-record. CHANGELOG [Docs] bullet count 16 -> 17. MD018-clean. Docs-only. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 44 ++++++++++++++++++-------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c73a0e95..5faac2897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 16๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 17๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049/#1057)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index be1124c51..323ccee90 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -43,12 +43,12 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter28 the loop is holding **16 stacked increment +the gate clears. As of iter32 the loop is holding **17 stacked increment PRs** plus **this document** (PR #1040). Separately, PR #942 (the original baseline draft) is green on every required check and waits only on one -non-author approval; it is not one of the 16 increments. +non-author approval; it is not one of the 17 increments. -The 16 increments and the merge-wave order once the gate clears: +The 17 increments and the merge-wave order once the gate clears: ```text #942 (approval-pending, not an increment) @@ -58,6 +58,7 @@ The 16 increments and the merge-wave order once the gate clears: -> #1037 (#946) -> #1051 -> #1038 (#948) -> #1050 -> #1039 (#950) -> #1049 + -> #1057 (#953) -> #1040 (this document) ``` @@ -572,14 +573,27 @@ incomplete; PR #834's useful commits are not yet decomposed onto `main`. prerequisite for any rebase wave). - **#1025** โ€” local Playwright E2E harness + `nanoid` pin (closes #1014); the harness the product-journey rehearsal will extend. - -**Remaining increments.** The full open-PR classification table (every -open PR at its exact head, with a `release_blocker` / `post_ga_committed` -/ `experimental` / `not_planned` decision + rationale) โ€” deferred until -the incident clears and the merge wave drains the loop's own stack, since -classifying ~60 PRs that cannot merge yet would go stale immediately; a -release-evidence manifest generator; the operability baseline; migration -rehearsal automation; then a synchronized version bump + `CHANGELOG` +- **#1057** โ€” `app/release/manifest.py` `build_release_manifest(...)`, a + pure assembler (no git / network / filesystem) that validates and + normalizes the supplied release facts (source commit, backend / + frontend versions, migration revisions, dependency-lock digests, + included PRs, known limitations, generated-at) into one immutable + JSON-serializable manifest; `is_ga_candidate` is `True` only when the + known-limitations list is empty (honesty rule); a `ValueError` names + the first field that fails validation. New `app/release/` package. + Cites NIST SP 800-218 and SLSA v1.2. + +**Remaining increments.** The pure manifest assembler landed (#1057); what +remains to make it a release-evidence artifact of record: SBOM generation +(SPDX / CycloneDX) wired into the build; signed build provenance / +attestation (SLSA v1.2); the operability baseline (SLI / SLO + dashboards ++ runbooks, linked to #951); migration rehearsal automation; the +per-dependency release-decision table; and the full open-PR classification +of record (every open PR at its exact head, with a `release_blocker` / +`post_ga_committed` / `experimental` / `not_planned` decision + +rationale) โ€” deferred until the incident clears and the merge wave drains +the loop's own stack, since classifying ~60 PRs that cannot merge yet +would go stale immediately. Then a synchronized version bump + `CHANGELOG` release section + `RELEASE_NOTES.md` once #946โ€“#952 reach `merge-ready` on their MVP increments. @@ -637,9 +651,11 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes. This revision (iter28) added PR #1056 -(the versioned baseline-report envelope) to the #951 list, taking the -stacked-PR count to 16. iter22 added PR #1049 (the tenant-authority +ships or the incident status changes. This revision (iter32) added PR #1057 +(the pure release-manifest assembler, a new `app/release/` package) as the +release-evidence increment for issue #953, taking the stacked-PR count to 17. +iter28 added PR #1056 (the versioned baseline-report envelope) to the #951 +list. iter22 added PR #1049 (the tenant-authority column-presence check) to the #950 list and PR #1050 (the lineage PROV-JSON projection) to the #948 list. iter20 added PR #1048 (transitive-dependency / 3NF assessment) to the #947 list. iter19 fixed the markdownlint MD018 line-start warnings From 3d1babab13841514fd9f857b2ae447bb1d482d4e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Wed, 2 Sep 2026 21:06:25 +0900 Subject: [PATCH 09/10] docs: add #1060 (#947 signed-waiver helper) to the increment lists Gate still frozen (main@8dc74692; .github#1531 queue oscillating ~1700-1900, no drainage). iter36 gap-baseline consolidation: record PR #1060 (pure sign_waiver / verify_waiver_signature HMAC-SHA256 tamper-evidence pair) in the #947 "This loop's increment PRs" list. Stacked-PR count 17 -> 18; #947 merge-wave chain extended to #1048 -> #1060; #947 "Remaining increments" reworded (signing core landed, persistence remains). CHANGELOG [Docs] bullet count 17 -> 18. MD018-clean. Docs-only. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 31 +++++++++++++++++--------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5faac2897..a1d9a7f8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 17๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049/#1057)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 18๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1060/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049/#1057)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 323ccee90..81feb0332 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -43,17 +43,17 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter32 the loop is holding **17 stacked increment +the gate clears. As of iter36 the loop is holding **18 stacked increment PRs** plus **this document** (PR #1040). Separately, PR #942 (the original baseline draft) is green on every required check and waits only on one -non-author approval; it is not one of the 17 increments. +non-author approval; it is not one of the 18 increments. -The 17 increments and the merge-wave order once the gate clears: +The 18 increments and the merge-wave order once the gate clears: ```text #942 (approval-pending, not an increment) -> #1024 -> #1025 - -> #1031 -> #1032 -> #1033 -> #1035 -> #1048 (#947 chain) + -> #1031 -> #1032 -> #1033 -> #1035 -> #1048 -> #1060 (#947 chain) -> #1036 -> #1041 -> #1045 -> #1056 (#951 chain) -> #1037 (#946) -> #1051 -> #1038 (#948) -> #1050 @@ -168,10 +168,19 @@ never described as 3NF proof. class `proposed`, never applied). It never infers a dependency from column names; unresolvable declared FDs are returned, not dropped. 13 golden fixtures. +- **#1060** โ€” `app/spec/waiver_record.py` (`sign_waiver` / + `verify_waiver_signature`): a pure, IO-free HMAC-SHA256 tamper-evidence + pair for assessment waivers. The canonical JSON folds the + signer / signed-at / key-id metadata in, so altering the metadata + invalidates the signature exactly as altering the waiver body does; + verification is constant-time. The caller supplies the secret key and it + is never stored, logged, or echoed into the record. Cites NIST FIPS + 198-1 and RFC 8785. **Remaining increments.** Row-level functional-dependency *discovery* from table data (a profiling service, out of scope for the pure analyzer); -persisted signed waiver records; the `EXPLAIN` pruning fixtures against a +persistence of the signed waiver records (the signing / verification core +landed in #1060); the `EXPLAIN` pruning fixtures against a real PostgreSQL; the versioned `assessment_run` persistence; a Rust core once the #951 profile shows a measured hotspot. @@ -651,11 +660,13 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes. This revision (iter32) added PR #1057 -(the pure release-manifest assembler, a new `app/release/` package) as the -release-evidence increment for issue #953, taking the stacked-PR count to 17. -iter28 added PR #1056 (the versioned baseline-report envelope) to the #951 -list. iter22 added PR #1049 (the tenant-authority +ships or the incident status changes. This revision (iter36) added PR #1060 +(the signed-waiver helper, `app/spec/waiver_record.py`) to the #947 list, +taking the stacked-PR count to 18. iter32 added PR #1057 (the pure +release-manifest assembler, a new `app/release/` package) as the +release-evidence increment for issue #953. iter28 added PR #1056 (the +versioned baseline-report envelope) to the #951 list. iter22 added PR #1049 +(the tenant-authority column-presence check) to the #950 list and PR #1050 (the lineage PROV-JSON projection) to the #948 list. iter20 added PR #1048 (transitive-dependency / 3NF assessment) to the #947 list. iter19 fixed the markdownlint MD018 line-start warnings From 375badd6225cabe0521c2b9c87ca692ff9b5f2c3 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 3 Sep 2026 01:23:18 +0900 Subject: [PATCH 10/10] docs: add #1063 (#953 CycloneDX SBOM generator) to the increment lists Gate still frozen (main@8dc74692; .github#1531 queue ~2100 and climbing every tick). iter40 gap-baseline consolidation: record PR #1063 (pure lockfile -> CycloneDX 1.6 parser) in the #953 "This loop's increment PRs" list. Stacked-PR count 18 -> 19; #953 merge-wave chain extended to #1057 -> #1063; #953 "Remaining increments" reworded (SBOM generator landed, SBOM signing + manifest linkage + SLSA provenance remain). CHANGELOG [Docs] bullet count 18 -> 19. MD018-clean. Docs-only. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_013SeQS8tSee5QVeyGpJ9SaY --- CHANGELOG.md | 2 +- docs/product-technical-gap-baseline.md | 35 ++++++++++++++++---------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1d9a7f8c..b75e2edb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## Unreleased -- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 18๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1060/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049/#1057)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. +- [Docs] ๐Ÿ“ **product-technical-gap-baseline.md ํ†ตํ•ฉ**: ์ƒ์šฉํ™”๊นŒ์ง€์˜ ๊ฒฉ์ฐจ๋ฅผ ๋‹จ์ผ ์ถ”์  ๋ฌธ์„œ๋กœ ์ •๋ฆฌํ–ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์šฉํ™” blocker(org CI ์ธ์‹œ๋˜ํŠธ `.github#1531`๋กœ 2026-08-20 ์ดํ›„ pg-erd-cloud main ๋ณ‘ํ•ฉ 0, merge-ready ์ฆ๋ถ„ PR 19๊ฑด + ๋ณธ ๋ฌธ์„œ ๋Œ€๊ธฐ)๋ฅผ ๋ช…์‹œํ•˜๊ณ , ์ด์Šˆ #946โ€“#953๋ณ„๋กœ ๊ธฐ๋Šฅ ๋ช…์„ธยทํ˜„ํ–‰ยทGapยท์ด๋ฒˆ ๋ฃจํ”„ ์ฆ๋ถ„ PR(#1024/#1025/#1031/#1032/#1033/#1035/#1048/#1060/#1036/#1041/#1045/#1056/#1037/#1051/#1038/#1050/#1039/#1049/#1057/#1063)ยท์ž”์—ฌ ์ฆ๋ถ„์„ ์ •๋ฆฌํ–ˆ์œผ๋ฉฐ, cross-repo(keyverse/contextual-orchestrator/wardnet/.github) ์—ฐ๊ณ„์™€ ์ƒํƒœ ๋ฒ”๋ก€, ํ‘œ์ค€ ์ธ์šฉ(APA 7th)์„ ํฌํ•จํ–ˆ์Šต๋‹ˆ๋‹ค. #949ยท#952ยท#953 ์ ˆ์€ ์ด์Šˆ ๋ณธ๋ฌธ์œผ๋กœ ์ฑ„์› ๊ณ , #952๋Š” ๊ธฐ์กด configuration-only `/chat/completions` ํ†ตํ•ฉ(`docs/llm-orchestrator-integration.md`)๊ณผ ์ •ํ•ฉํ•˜๋„๋ก ๋‚จ์€ ์ž‘์—…(์ž๊ฒฉ ์ฆ๋ช… ๊ฒฝ๊ณ„ยทtenant contextยทdiscovery/routing ์œ„์ž„)๋งŒ ๊ธฐ์ˆ ํ•ฉ๋‹ˆ๋‹ค. PR #942์˜ ์ดˆ์•ˆ ๋ฒ„์ „์„ ๋Œ€์ฒดยทํ™•์žฅํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ ๋ณต๊ตฌ ์‹œ ์ •ํ•ฉํ™”ํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **Cryptography 50+ ๋ณด์•ˆ ๊ฒฝ๊ณ„ ๊ฐฑ์‹ **: `pyproject.toml`๊ณผ ๋‘ hash-locked ์š”๊ตฌ์‚ฌํ•ญ ํŒŒ์ผ์„ ๋™์ผํ•œ Cryptography 50+ ํ•ด์„์œผ๋กœ ์ •ํ•ฉํ™”ํ•˜์—ฌ PKCS#7 ์˜ค๋ฅ˜ยทํƒ€์ด๋ฐ ๊ตฌ๋ถ„์œผ๋กœ ์ธํ•œ CVE-2026-69247 ์™„ํ™”๋ฅผ ์‹ค์ œ ์„ค์น˜ยท๊ฒ€์ฆ ๊ฒฝ๋กœ์— ๋ฐ˜์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. - [FE] โšก **๊ฒ€์ƒ‰ ๋…ธ๋“œ ์ฐธ์กฐ ์•ˆ์ •ํ™” ๋ฐ ์ˆœ์ฐจ ์Šค๋ƒ…์ƒท ํด๋ง**: ๊ฐ™์€ ์ •๊ทœํ™” ๊ฒ€์ƒ‰์–ด์™€ ์›๋ณธ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ์—๋Š” ์žฅ์‹๋œ `node.data` ์ฐธ์กฐ๋ฅผ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋ž˜๊ทธ ์ค‘ ๋ถˆํ•„์š”ํ•œ ํ•˜์œ„ ๋ Œ๋”๋ง๊ณผ ํ• ๋‹น์„ ์ค„์ž…๋‹ˆ๋‹ค. ์Šค๋ƒ…์ƒท ํด๋ง์€ ์ด์ „ ์š”์ฒญ์ด ๋๋‚œ ๋’ค์—๋งŒ ๋‹ค์Œ ์š”์ฒญ์„ ์˜ˆ์•ฝํ•˜๋ฉฐ, ์„ ํƒ ๋ณ€๊ฒฝยท์–ธ๋งˆ์šดํŠธ ํ›„ ๋„์ฐฉํ•œ ์˜ค๋ž˜๋œ ์„ฑ๊ณต ๋˜๋Š” ์‹คํŒจ ์‘๋‹ต์„ ๋ฌด์‹œํ•ฉ๋‹ˆ๋‹ค. - [BE] ๐Ÿ”’ **๊ณต์œ  export ์ „ ๊ฒฝ๋กœ redaction**: ๊ณต๊ฐœ share์˜ SQL / index-design / reversing-spec export์—์„œ ์ฝ”๋ฉ˜ํŠธยท`example_value`๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋กœ ๋ˆ„์ถœ์„ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 81feb0332..b09ad4abd 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -43,12 +43,12 @@ was found and is being addressed in that repo. **Consequence for this baseline:** every gap increment below is shipped as a small, tested, mypy-clean, 100%-docstring PR and **held merge-ready** until -the gate clears. As of iter36 the loop is holding **18 stacked increment +the gate clears. As of iter40 the loop is holding **19 stacked increment PRs** plus **this document** (PR #1040). Separately, PR #942 (the original baseline draft) is green on every required check and waits only on one -non-author approval; it is not one of the 18 increments. +non-author approval; it is not one of the 19 increments. -The 18 increments and the merge-wave order once the gate clears: +The 19 increments and the merge-wave order once the gate clears: ```text #942 (approval-pending, not an increment) @@ -58,7 +58,7 @@ The 18 increments and the merge-wave order once the gate clears: -> #1037 (#946) -> #1051 -> #1038 (#948) -> #1050 -> #1039 (#950) -> #1049 - -> #1057 (#953) + -> #1057 -> #1063 (#953) -> #1040 (this document) ``` @@ -591,11 +591,19 @@ incomplete; PR #834's useful commits are not yet decomposed onto `main`. known-limitations list is empty (honesty rule); a `ValueError` names the first field that fails validation. New `app/release/` package. Cites NIST SP 800-218 and SLSA v1.2. - -**Remaining increments.** The pure manifest assembler landed (#1057); what -remains to make it a release-evidence artifact of record: SBOM generation -(SPDX / CycloneDX) wired into the build; signed build provenance / -attestation (SLSA v1.2); the operability baseline (SLI / SLO + dashboards +- **#1063** โ€” `app/release/sbom.py` (`parse_pip_lock` / `parse_npm_lock` + / `build_sbom`): a pure text/JSON parser that turns the lockfiles the + repo already commits into a **CycloneDX 1.6** `bom` โ€” no `pip`/`npm` + run, no dependency resolution, no network. Components are de-duplicated + by purl and sorted by `(type, name, version)`; blank envelope metadata + raises a `ValueError` naming the field. Cites OWASP CycloneDX 1.6 and + NTIA (2021) SBOM minimum elements. + +**Remaining increments.** The pure manifest assembler landed (#1057) and +the CycloneDX SBOM generator landed (#1063); what remains to make this a +release-evidence artifact of record: signed build provenance / +attestation (SLSA v1.2); signing the SBOM and referencing it from the +manifest by digest; the operability baseline (SLI / SLO + dashboards + runbooks, linked to #951); migration rehearsal automation; the per-dependency release-decision table; and the full open-PR classification of record (every open PR at its exact head, with a `release_blocker` / @@ -660,10 +668,11 @@ citations for its increment. ## How this document is maintained The autonomous review/merge loop updates this file each time a gap increment -ships or the incident status changes. This revision (iter36) added PR #1060 -(the signed-waiver helper, `app/spec/waiver_record.py`) to the #947 list, -taking the stacked-PR count to 18. iter32 added PR #1057 (the pure -release-manifest assembler, a new `app/release/` package) as the +ships or the incident status changes. This revision (iter40) added PR #1063 +(the CycloneDX SBOM generator, `app/release/sbom.py`) to the #953 list, +taking the stacked-PR count to 19. iter36 added PR #1060 (the signed-waiver +helper, `app/spec/waiver_record.py`) to the #947 list. iter32 added PR #1057 +(the pure release-manifest assembler, a new `app/release/` package) as the release-evidence increment for issue #953. iter28 added PR #1056 (the versioned baseline-report envelope) to the #951 list. iter22 added PR #1049 (the tenant-authority