Files
kite/.planning/v1.0-MILESTONE-AUDIT.md
curo1305 eaa3399ec0 docs: add shared module map to CLAUDE.md, SECURITY.md, planning artifacts
- CLAUDE.md: add Code Standards section with backend and frontend shared
  module maps, component architecture rules, duplication checklist, and
  no-dead-code enforcement rule
- SECURITY.md: Phase 02 + 03 security audit results (all threats CLOSED)
- .planning: update milestone audit, config, and add plan/UAT files for
  phases 01, 02-06, and 06.2-05

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 16:10:59 +02:00

26 KiB

milestone, audited, status, scores, gaps, tech_debt, nyquist
milestone audited status scores gaps tech_debt nyquist
v1.0 2026-05-30T00:00:00Z gaps_found
requirements phases_verified integration_blockers integration_warnings flows_complete
44/54 2/6 4 7 3/6
requirements integration flows
id status phase claimed_by_plans completed_by_plans verification_status evidence
SHARE-02 partial 4
04-04-PLAN.md
06.1-01-PLAN.md
06.1-01-PLAN.md
gaps_found Two distinct bugs: (1) backend/api/documents.py line 542 checks doc.user_id != current_user.id and raises 404 — share recipients get 404 on GET /api/documents/{id} despite having a valid Share record; (2) SharedView.vue accesses share.document?.original_name, share.shared_by, share.document?.created_at but /api/shares/received returns a flat object with filename/owner_handle/created_at — all metadata fields render blank.
id status phase claimed_by_plans completed_by_plans verification_status evidence
DOC-01 partial 4
04-01-PLAN.md
04-09-PLAN.md
04-09-PLAN.md
missing Owners can view document metadata and extracted text. Share recipients cannot — documents.py:542 enforces ownership-only check, returning 404 for recipients who navigate to /document/{id}. No share-grant lookup performed before the 404.
id status phase claimed_by_plans completed_by_plans verification_status evidence
SHARE-03 partial 4
04-04-PLAN.md
06.1-01-PLAN.md
06.1-01-PLAN.md
gaps_found ShareCreate model has no permission field. grant_share hardcodes permission='view'. No PATCH /api/shares/{id} endpoint exists to change permission after creation. SHARE-03 requires 'owner controls permission level' — only the 'view-only default' half is satisfied. The stored permission field in the shares table cannot be changed through any API endpoint.
id status phase claimed_by_plans completed_by_plans verification_status evidence
SHARE-05 partial 4
04-04-PLAN.md
06.1-01-PLAN.md
06.1-01-PLAN.md
gaps_found is_shared computed per document in documents.py lines 433-445 and 498-510 (two separate DB subqueries per list request). Zero occurrences of is_shared in any .vue or .js file. DocumentCard.vue has no visual indicator for shared documents. 06.1-VALIDATION added test_share_indicator_in_owner_list which confirms is_shared=True in the API response — but no frontend component reads or renders it.
id status phase claimed_by_plans completed_by_plans verification_status evidence
STORE-06 partial 3
03-02-PLAN.md
03-02-SUMMARY.md (STORE-06)
missing MinIO path: services/storage.py:168-175 implements atomic CASE WHEN quota decrement — correct for MinIO documents. Cloud path: delete_document() calls self._backend().delete_object(doc.object_key) where _backend() always returns MinIOBackend regardless of doc.storage_backend. Cloud-stored documents: (1) MinIO delete_object gets NoSuchKey (silently swallowed); (2) MinIO quota decremented even though no quota was charged at cloud upload; (3) actual file in Google Drive / OneDrive / Nextcloud / WebDAV is never deleted. Additionally, test_delete_decrements_quota is @pytest.mark.xfail(strict=False) — ROADMAP phase gate requires INTEGRATION=1 confirmation against live PostgreSQL.
id status phase claimed_by_plans completed_by_plans verification_status evidence
SEC-09 partial 4
04-07-PLAN.md
05-05-PLAN.md
04-07-SUMMARY.md
05-05-SUMMARY.md
partial Admin-initiated account deletion (admin.py lines 518-565) correctly purges all CloudConnection rows and calls delete_user_files() before MinIO+DB cleanup — SEC-09 satisfied for the account deletion path. However, user-initiated document deletion (services/storage.delete_document) does not call get_storage_backend_for_document — cloud provider files are orphaned when a user deletes a cloud-stored document.
id status phase claimed_by_plans completed_by_plans verification_status evidence
ADMIN-06 partial 4
04-06-PLAN.md
06.1-02-PLAN.md
06.1-02-PLAN.md
gaps_found GET /api/admin/audit-log JSON viewer works end-to-end. Filter behavioral tests pass (test_audit_log_filter_by_event_type added in commit 451fff1). GET /api/admin/audit-log/export: AuditLogTab.vue:191 uses window.location.href which sends no Authorization: Bearer header. get_current_admin requires HTTPBearer — CSV export always returns 403.
id status phase claimed_by_plans completed_by_plans verification_status evidence
CLOUD-03 partial 5
05-06-PLAN.md
05-06-SUMMARY.md
human_needed PATCH /api/users/me/default-storage fully implemented (cloud.py:927, registered in main.py). updateDefaultStorage() exported from client.js:448. However, updateDefaultStorage() is never imported or called by any Vue component. SettingsCloudTab.vue renders cloud connections but has no radio/select to change the default storage backend. Users cannot change their default backend through the UI.
id status phase claimed_by_plans completed_by_plans verification_status evidence
FOLD-01 partial 4
04-03-PLAN.md
04-03-PLAN.md
missing _folder_to_dict() in folders.py:65 returns {id, name, parent_id, user_id, created_at} — no doc_count field. FolderDeleteModal.vue:31 and FolderRow.vue:32 display folder.doc_count ?? 0. FOLD-01 requires 'delete confirms content count before proceeding' — confirmation always shows '0 documents' regardless of actual folder content.
id status phase claimed_by_plans completed_by_plans verification_status evidence
FOLD-05 partial 4
04-03-PLAN.md
04-03-PLAN.md
missing SearchBar rendered with v-if='currentFolderId' in FileManagerView.vue — hidden at the root level (no folder selected). Users browsing the root document library have no search input. FOLD-05 requires 'Full-text search across user's documents' — search is only available when inside a folder, not at root.
blocker description
SHARE-02 / DOC-01 — Share recipient blocked from document detail documents.py:542 checks doc.user_id != current_user.id → HTTPException(404). No share-grant lookup performed. Recipients with valid Share records cannot access GET /api/documents/{id}, breaking the shared document detail view. SharedView.vue also accesses wrong field paths (share.document?.original_name instead of share.filename etc.) — all metadata renders blank even on the list.
blocker description
STORE-06 / SEC-09 — Cloud document delete corrupts quota and orphans files services/storage.delete_document() calls self._backend().delete_object() where _backend() always returns MinIOBackend. Cloud-stored docs: MinIO delete_object silently fails (NoSuchKey), MinIO quota decremented unconditionally, actual cloud provider file never deleted.
blocker description
ADMIN-06 — Audit log CSV export always returns 403 AuditLogTab.vue:191 uses window.location.href for CSV export. Browser navigation strips Authorization: Bearer header. Backend endpoint requires HTTPBearer. All CSV export clicks result in 403.
blocker description
CLOUD-03 — Default storage UI orphaned updateDefaultStorage() exported from client.js but never called by any component. No frontend UI exists to change the default storage backend.
name breaks_at affected_requirements
Recipient views shared document detail documents.py:542 ownership-only check
SHARE-02
DOC-01
name breaks_at affected_requirements
User deletes cloud-stored document services/storage.delete_document() — MinIO backend hardcoded
STORE-06
SEC-09
name breaks_at affected_requirements
Admin exports audit log as CSV AuditLogTab.vue:191 window.location.href drops Bearer token
ADMIN-06
phase items
01-infrastructure-foundation
No VERIFICATION.md exists (phase not formally verified by gsd-verifier)
VALIDATION.md: nyquist_compliant: true, audited 2026-05-30
phase items
02-users-authentication
VERIFICATION.md exists (gaps_found 4/5) — SC5 gap closed by Phase 3, no re-verification run
No VALIDATION.md — Nyquist compliance MISSING for Phase 2
4 human verification items pending: TOTP enrollment e2e, password reset email, sign out all devices, admin panel visuals
phase items
03-document-migration-multi-user-isolation
No VERIFICATION.md exists (phase not formally verified)
VALIDATION.md: nyquist_compliant: false, status: draft — Nyquist PARTIAL
Document.user_id ORM column has nullable=True but DB has NOT NULL constraint (migration 0003 alters it) — ORM/schema drift
test_delete_decrements_quota is xfail(strict=False) on SQLite — INTEGRATION=1 gate requires live PostgreSQL to confirm
phase items
04-folders-sharing-quotas-document-ux
No VERIFICATION.md exists (phase not formally verified)
VALIDATION.md: nyquist_compliant: false, status: draft — Nyquist PARTIAL
AdminView.vue has no frontend role guard — unauthenticated-role users who navigate to /admin see full UI (all backend calls return 403 but no redirect occurs)
FOLD-01: _folder_to_dict() omits doc_count; delete confirmation always shows 0 documents
FOLD-05: SearchBar hidden at root level (v-if='currentFolderId')
SHARE-05: is_shared computed per document (2 DB subqueries) but never rendered in any Vue component
SHARE-03: permission hardcoded 'view', no PATCH endpoint to change it
phase items
05-cloud-storage-backends
VERIFICATION.md: human_needed — 6 items require live cloud credentials (Google OAuth, OneDrive OAuth, live Nextcloud/WebDAV server)
VALIDATION.md: nyquist_compliant: true, audited 2026-05-30
CLOUD-05 REQUIRES_REAUTH transition implemented for OAuth providers only (Google Drive, OneDrive). Nextcloud/WebDAV credential failures produce generic 502 — no REQUIRES_REAUTH state for non-OAuth backends. Spec-compliant but UX gap.
_doc_to_dict() omits storage_backend and folder_id — document list response cannot distinguish cloud vs local documents
CLOUD-03: updateDefaultStorage() exported but no UI element calls it
phase items
06.1-close-v1-audit-gaps
VERIFICATION.md: stale (written before commit 451fff1 which added audit filter test). 06.1-VALIDATION.md supersedes.
VALIDATION.md: nyquist_compliant: true, gaps_found: 3, gaps_resolved: 2, gaps_manual: 1
STORE-06 INTEGRATION=1 gate: manual-only — requires live PostgreSQL Docker stack to confirm
conftest.py WR-03: dependency_overrides not cleared on exception in async_client fixture (low-probability correctness gap)
phase items
all
REQUIREMENTS.md checkboxes are stale — 22 satisfied requirements still show [ ]. Not maintained during execution.
CLAUDE.md specifies ES256 JWT algorithm, email_hmac deterministic index, fgp token fingerprint claim — none implemented (HS256, plaintext email, no fingerprint). Outside 54 v1 REQ-IDs; v2 hardening scope.
compliant_phases partial_phases missing_phases overall
1
5
6.1
3
4
2
partial

DocuVault v1.0 — Milestone Audit Report

Milestone: v1.0 Audited: 2026-05-30 Phases audited: 1, 2, 3, 4, 5, 6.1 (Phase 6 not started — excluded) Status: ⚠ GAPS FOUND


Executive Summary

All 6 planned v1 phases executed and marked complete. Phase 5 formally verified (7/7 truths, human_needed). Phase 2 VERIFICATION.md status=gaps_found (4/5); gap confirmed closed by Phase 3. Phases 1, 3, 4 have no VERIFICATION.md. Phase 6.1 VALIDATION.md supersedes its stale VERIFICATION.md.

The integration check found 4 blockers and 7 warnings. Ten requirements are partially satisfied, primarily due to frontend wiring gaps and a cloud-delete path defect.

Metric Score
Requirements satisfied 44/54 (81%)
Requirements partial 10/54 (19%)
Requirements unsatisfied 0/54
Phases formally verified 2/6 (Phases 2, 5)
Nyquist compliant 3/6 phases
Test gate 309 passed, 1 pre-existing failure (test_extract_docx — missing python-docx module; unrelated to milestone scope)

Requirements Coverage

Satisfied (44/54)

Phase REQ-IDs Count
1 — Infrastructure STORE-01, STORE-02, STORE-07 3
2 — Auth AUTH-01, AUTH-02, AUTH-03, AUTH-04, AUTH-05, AUTH-06, AUTH-07, AUTH-08, SEC-01, SEC-02, SEC-03, SEC-05, SEC-06, SEC-07, ADMIN-01, ADMIN-02, ADMIN-03, ADMIN-04, ADMIN-05, ADMIN-07 20
3 — Documents STORE-03, STORE-04, STORE-05, STORE-08, SEC-04, DOC-03, DOC-04, DOC-05 8
4 — Folders/Sharing FOLD-02, FOLD-03, FOLD-04, SHARE-01, SHARE-04, SEC-08, DOC-02 7
5 — Cloud CLOUD-01, CLOUD-02, CLOUD-04, CLOUD-05, CLOUD-06, CLOUD-07 6

Total satisfied: 44

Notable confirmations from integration check:

  • STORE-08: Zero BackgroundTasks usages remain; all async work runs through Celery (document_tasks.py, email_tasks.py).
  • DOC-02: PDF proxy chain complete — fetchDocumentContent() → Bearer-authenticated GET /api/documents/{id}/contentget_storage_backend_for_document() → byte stream → blob URL.
  • SEC-07: get_regular_user raises 403 for admin role on all /api/documents/* endpoints — Phase 2 gap confirmed closed by Phase 3.
  • SEC-08: CloudConnectionOut whitelist (provider, display_name, connected_at, status only) used at cloud.py:637,661credentials_enc excluded from all responses.

Partial (10/54) — Blockers and Warnings

REQ-ID Phase Severity Root Cause
SHARE-02 4 BLOCKER Recipients get 404 on GET /api/documents/{id} (ownership check only). SharedView.vue field names wrong (blank metadata display).
DOC-01 4 BLOCKER Owners: . Share recipients: 404 at documents.py:542 (doc.user_id != current_user.id, no share-grant check).
STORE-06 3 BLOCKER MinIO delete-path correct. Cloud delete-path: MinIO backend called unconditionally → quota corrupted, cloud file orphaned.
SEC-09 4 BLOCKER Admin account deletion: . User-initiated document delete: cloud provider file not deleted (only MinIO attempted).
ADMIN-06 4 BLOCKER JSON audit viewer: . CSV export: window.location.href drops Bearer header → 403.
SHARE-03 4 WARNING permission="view" hardcoded. No PATCH /api/shares/{id} endpoint. Owner cannot change permission level.
SHARE-05 4 WARNING is_shared computed per document (2 DB subqueries / request) but never rendered by any Vue component.
CLOUD-03 5 WARNING PATCH /api/users/me/default-storage implemented. updateDefaultStorage() exported but no UI calls it.
FOLD-01 4 WARNING _folder_to_dict() omits doc_count. Delete confirmation modal always shows "0 documents".
FOLD-05 4 WARNING SearchBar hidden at root (v-if="currentFolderId"). Full-text search unavailable in root document library.

Phase Verification Status

Phase VERIFICATION.md Status Notes
01 — Infrastructure Foundation MISSING Unverified Phase marked complete; no formal verification run
02 — Users & Authentication exists gaps_found (4/5) SC5 gap (admin JWT → 403 on docs) closed by Ph3; confirmed by integration check
03 — Document Migration MISSING Unverified Phase marked complete; no formal verification run
04 — Folders, Sharing, Quotas MISSING Unverified Phase marked complete; no formal verification run
05 — Cloud Storage Backends exists human_needed (7/7) All must-haves verified; 6 human UAT items require live cloud credentials
6.1 — Gap Closure exists (stale) Superseded by VALIDATION.md 06.1-VALIDATION.md: gaps_found 3, resolved 2, manual 1

Nyquist Coverage

Phase VALIDATION.md nyquist_compliant Action
01 — Infrastructure Foundation audited 2026-05-30 true None
02 — Users & Authentication MISSING /gsd:validate-phase 2
03 — Document Migration exists, status: draft false /gsd:validate-phase 3
04 — Folders, Sharing, Quotas exists, status: draft false /gsd:validate-phase 4
05 — Cloud Storage Backends audited 2026-05-30 true None
6.1 — Gap Closure audited 2026-05-30 true None

Critical Blockers (5)

BLOCKER-1 — Share Recipient Cannot View Document Metadata (SHARE-02, DOC-01)

File: backend/api/documents.py line 542 Root cause: if doc is None or doc.user_id != current_user.id: raise HTTPException(404) — no share-grant check. Broken flow: SharedView.vue → click shared item → DocumentView.vue → getDocument(id) → 404 for recipient despite valid Share record. Secondary bug: SharedView.vue accesses share.document?.original_name, share.shared_by, share.document?.created_at but /api/shares/received returns a flat object (filename, owner_handle, created_at). All metadata renders blank even on the list. Fix (backend): In get_document(), after the ownership 404, add: check Share table for (document_id=doc_id, recipient_id=current_user.id) and allow if found. Fix (frontend): In SharedView.vue, update field access to match flat response shape.

BLOCKER-2 — Cloud Document Delete Corrupts Quota and Orphans Files (STORE-06, SEC-09)

File: backend/services/storage.py (delete_document function) Root cause: self._backend().delete_object(doc.object_key) always uses MinIOBackend regardless of doc.storage_backend. Then decrements MinIO quota unconditionally. Impact: Cloud-stored documents: (1) MinIO delete_object gets NoSuchKey (silently swallowed), (2) MinIO quota decremented below actual usage, (3) actual cloud provider file never deleted → GDPR Article 17 obligation not met for cloud storage. Fix: Use get_storage_backend_for_document(doc, session) in delete_document(). Gate quota decrement on doc.storage_backend == "minio".

BLOCKER-3 — Admin Audit Log CSV Export Always Returns 403 (ADMIN-06)

File: frontend/src/components/admin/AuditLogTab.vue line 191 Root cause: window.location.href = '/api/admin/audit-log/export?${params}' — browser navigation strips the Authorization: Bearer header. get_current_admin requires HTTPBearer. Fix: Replace window.location.href with fetch() using Authorization: Bearer ${accessToken}, then create a Blob URL for download. The fetchDocumentContent() pattern in client.js is the correct model.

BLOCKER-4 — Default Storage Backend Has No Frontend UI (CLOUD-03)

File: frontend/src/components/settings/SettingsCloudTab.vue Root cause: updateDefaultStorage() is exported from client.js:448 but never imported or called by any component. SettingsCloudTab.vue has no UI control to select a default backend. Fix: Add a "Set as default" button or radio to each connected provider row in SettingsCloudTab.vue; wire it to updateDefaultStorage(provider).


Warnings (7)

# Description Requirement
W-1 is_shared computed per document (2 subqueries per list request) but no Vue component renders it SHARE-05
W-2 SHARE-03: permission hardcoded to "view"; no PATCH /api/shares/{id} endpoint SHARE-03
W-3 _folder_to_dict() omits doc_count — delete confirmation modal always shows "0 documents" FOLD-01
W-4 SearchBar hidden at root level (v-if="currentFolderId") — search unavailable in root library FOLD-05
W-5 Document.user_id ORM column nullable=True; DB has NOT NULL constraint (migration 0003) — ORM/schema drift STORE-03
W-6 AdminView.vue has no frontend role guard — regular users who navigate to /admin see full UI; backend returns 403 but no redirect
W-7 CLAUDE.md specifies ES256 JWT, email_hmac index, fgp fingerprint claim — none implemented (HS256, plaintext email, no fingerprint). v2 hardening scope, outside 54 v1 REQ-IDs. v2

E2E Flow Results

Flow Status Break Point
MinIO upload → quota updated → Celery AI classification COMPLETE
Password reset → TOTP gate on next login COMPLETE
Cloud upload → authenticated content proxy (blob URL) COMPLETE
Share document → "Shared with me" list → recipient views detail BROKEN documents.py:542 ownership-only check + SharedView field mismatch
User deletes cloud-stored document → files purged BROKEN delete_document() hardcodes MinIOBackend
Admin views audit log → exports CSV ⚠️ PARTIAL JSON viewer works; CSV export → 403 (no Bearer in window.location.href)

Integration Wiring Summary (47 connections)

Connection Status
Auth deps (get_regular_user / get_current_admin) on all Phase 3-5 endpoints All wired (verified across documents.py, folders.py, shares.py, cloud.py, audit.py)
Phase 2 admin gap (admin JWT → 403 on /api/documents/*) Closed in Phase 3 by get_regular_user
Atomic quota at upload (MinIO path) Wired (documents.py:342-346)
Atomic quota decrement at delete (MinIO path) Wired (services/storage.py:168-175)
Atomic quota decrement at delete (cloud path) Not wired — MinIOBackend hardcoded
Cloud document content proxy (authenticated fetch → blob URL) Wired
Admin delete: cloud cleanup → MinIO cleanup → DB delete Wired (admin.py:518-565)
User-initiated doc delete: cloud provider cleanup Not wired
Share recipient access to /api/documents/{id}/content Wired (content proxy uses get_storage_backend_for_document)
Share recipient access to GET /api/documents/{id} metadata Ownership check blocks recipients
Admin audit log JSON viewer Wired end-to-end
Admin audit log CSV export Bearer header dropped by window.location.href
Default storage backend selection UI updateDefaultStorage() orphaned — no UI calls it
HKDF credential encryption through all cloud flows Wired
write_audit_log() called from documents (3), shares (2), folders (3), cloud (4) All wired
All API routers registered in main.py Confirmed
get_storage_backend_for_document() factory in content proxy + Celery task Wired
SHARE-05 is_shared computed in API → frontend Computed, never rendered

Tech Debt Summary

Phase 01: No VERIFICATION.md. VALIDATION.md compliant.

Phase 02: VERIFICATION.md gaps_found (Phase 2 SC5 closed by Phase 3). No VALIDATION.md (Nyquist MISSING for Phase 2). 4 human verification items pending.

Phase 03: No VERIFICATION.md. VALIDATION.md draft (Nyquist PARTIAL). Document.user_id ORM nullable vs DB NOT NULL drift. test_delete_decrements_quota xfail — INTEGRATION=1 required.

Phase 04: No VERIFICATION.md. VALIDATION.md draft (Nyquist PARTIAL). AdminView.vue missing frontend role guard. Multiple UI gaps (FOLD-01, FOLD-05, SHARE-05, SHARE-03, SHARE-02 field names).

Phase 05: VERIFICATION.md human_needed (must-haves all confirmed). VALIDATION.md compliant. CLOUD-03 UI orphaned. CLOUD-05 REQUIRES_REAUTH only for OAuth providers.

Phase 06.1: VERIFICATION.md stale (superseded). VALIDATION.md compliant. STORE-06 manual gate pending. conftest.py WR-03 teardown gap.

Cross-cutting: REQUIREMENTS.md checkboxes not maintained (22 satisfied reqs still show [ ]). CLAUDE.md v2 hardening items (ES256, email_hmac, fgp fingerprint) not yet implemented.


Remediation Guide

Run Nyquist validation first (may close some verification gaps retroactively):

/gsd:validate-phase 2
/gsd:validate-phase 3
/gsd:validate-phase 4

Then insert closure phases for remaining blockers:

/clear then:
/gsd:phase --insert 6.2 "Close v1 sharing + cloud-delete + CSV export gaps"
/gsd:discuss-phase 6.2
/gsd:plan-phase 6.2
/gsd:execute-phase 6.2

Suggested scope for Phase 6.2 (all small fixes, could ship as one phase):

Fix Files Effort REQ-IDs
Share recipient access: add share-grant check to get_document() documents.py:542 ~15 lines SHARE-02, DOC-01
Fix SharedView.vue field names SharedView.vue ~10 lines SHARE-02
Cloud delete: use get_storage_backend_for_document() + gate quota decrement services/storage.py ~25 lines STORE-06, SEC-09
Audit CSV export: fetch() + Bearer + blob download AuditLogTab.vue:191 ~20 lines ADMIN-06
Default storage UI: "Set as default" button in SettingsCloudTab SettingsCloudTab.vue ~30 lines CLOUD-03
Add is_shared indicator to DocumentCard.vue DocumentCard.vue ~15 lines SHARE-05
Add doc_count to _folder_to_dict() folders.py:65 ~10 lines FOLD-01
Remove v-if="currentFolderId" gate from SearchBar FileManagerView.vue ~5 lines FOLD-05
Add PATCH /api/shares/{id} permission endpoint shares.py ~30 lines SHARE-03
Add frontend role guard to AdminView route or component router/index.js or AdminView.vue ~10 lines
Confirm test_delete_decrements_quota under INTEGRATION=1 test_quota.py:196 manual STORE-06

Also available:

  • cat .planning/v1.0-MILESTONE-AUDIT.md — this report
  • /gsd:complete-milestone v1.0 — proceed with gaps noted (accept as tech debt)

Audited: 2026-05-30 Auditor: Claude (gsd-audit-milestone) Integration checker: gsd-integration-checker (155 tool calls, 47 connections verified)