feat(tenant): scoped archive export/import slice 1 - #1465
Conversation
|
Warning Review limit reachedNext included review available in 59 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (9)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
PR governance metadata gate update for PR governance metadata gate is waiting on current-head requirements; see the latest check for pending reasons. |
|
@coderabbitai review |
|
|
Current-head local verification for |
|
Current-head review disposition for 70596e2: the five Devin threads were rechecked. The O(n) archive lookup is an explicitly bounded slice-1 limitation; fingerprint matching is the intentional strong-fingerprint idempotency contract; export fields are sanitized at ingestion; task relinking normalizes self-generated IDs; and email rows are flushed before dependent tasks. These are informational design notes, not unresolved source findings. The focused security regression suite is green; hosted Checks and independent review remain the merge gates. |
Supports #1428
PR 제목 (Title)
feat(tenant): scoped archive export/import slice 1
목적 (Purpose) / Description
First verifiable slice of the tenant export/reimport P0 buyer gap tracked in #1428 and documented in
docs/product-technical-gap-baseline.md("Tenant export/reimport"). This slice makes the round trip real: an organization+user-scoped export of the email/thread/task domain as a deterministic, versioned archive bundle, and a dedupe-safe import that preserves opaque public ids and source provenance. Issue #1428 tracks the full multi-slice gap, so this PR references it withSupports #1428rather than an auto-close keyword.주요 변경 사항 (Key Changes)
schema_versionstamped in the manifest).schema_version; validation fails closed (archive_schema_unsupported) on unsupported versions.error_codes mapped from exception types only:archive_schema_unsupported,archive_scope_mismatch,archive_bundle_malformed.backend/main.pybehind the default signed-session dependency (PRIVATE_API_DEPENDENCIES).docs/architecture/tenant-archive-contract.md.Type of change
Out of scope (later slices)
Attachment bytes, content/project graph, embedding regeneration, zip packaging, size caps, audit events.
변경 범위 / 영향도 (Scope / Impacted Areas)
변경 사항 표 (Change Table)
backend/services/tenant_archive_service.pybackend/api/tenant_archive.pybackend/main.py/api/*routers uniformly protected by the default signed-session dependency.backend/tests/test_tenant_archive_service.pybackend/tests/test_tenant_archive_api.pybackend/tests/test_tenant_archive_postgres.pydocs/architecture/tenant-archive-contract.mdschema_version, scoping, and exclusion rules reviewers can rely on for later slices.Sequence Diagram(s)
Export/import round trip:
sequenceDiagram participant C as Client (signed session) participant A as backend/api/tenant_archive router participant S as tenant_archive_service participant D as PostgreSQL (scoped rows) C->>A: POST export (org+user scope) A->>A: default signed-session dependency check A->>S: export(...) S->>D: SELECT email/thread/task rows filtered by owner_user_id + organization_id Note over S: credentials-bearing tables excluded<br/>manifest.schema_version stamped S-->>C: deterministic archive bundle C->>A: POST import (bundle) A->>A: default signed-session dependency check A->>S: import(bundle) S->>S: validate manifest.schema_version -> else archive_schema_unsupported S->>S: scope mismatch -> archive_scope_mismatch<br/>malformed payload -> archive_bundle_malformed S->>D: INSERT missing rows keyed by opaque public ids + source provenance Note over S,D: duplicates skipped, ids/provenance preserved S-->>C: import result (created/skipped counts)검증 (Verification)
Commands and results (pasted exactly):
PYTHONWARNINGS=error python -m pytest tests/test_tenant_archive_service.py tests/test_tenant_archive_api.py -q→ 25 passedPYTHONWARNINGS=error python -m pytest tests/test_tenant_archive_postgres.py -q→ 1 passed (real PostgreSQL round trip incl. second-import all-skipped)Checklist: