Task — engineering-spec@1

"DOC PAdES-B-LT format + year-9 LTV re-stamping — extend B-T signatures with validation data + re-timestamp before signature/TS authority expires"

draftTASK-DOC-011
module doc · class product · priority p0 · created 2026-05-17 · shipped null
depends on TASK-DOC-002 · blocks none

§1 — Description (BCP-14 normative)

The DOC service MUST ship LTV extension at services/doc/src/ltv/ extending B-T signatures to B-LT format and re-stamping at year-9, embedding fresh validation data, immutable audit, 4 memory audit kinds.

  1. MUST validate ltv_operation against closed enum per DEC-1802.
  1. MUST validate ltv_status against closed enum per DEC-1803.
  1. MUST extend B-T → B-LT at extender.rs::extend(signature) per DEC-1800:
  1. MUST schedule year-9 re-stamping per DEC-1801 — TASK-MCP-007 cron monthly, scans all doc_documents with signatures aged ≥9 years.
  1. MUST never alter the original signature bytes per DEC-1804 — only embed additional validation data + add new timestamp layer.
  1. MUST define table at migration 0011: ``sql CREATE TABLE doc_ltv_operations ( operation_id UUID PRIMARY KEY, tenant_id UUID NOT NULL, document_id UUID NOT NULL, operation TEXT NOT NULL CHECK (operation IN ('extend_bt_to_blt','restamp_blt')), signature_source TEXT NOT NULL, -- 'qtsp' | 'aatl' | 'vn_ca' | 'imported' original_sig_age_days INT NOT NULL, status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','completed','failed','deferred')), new_validation_data_added BYTEA, new_timestamp_token BYTEA, failure_reason TEXT, trace_id CHAR(32), created_at TIMESTAMPTZ NOT NULL DEFAULT now(), completed_at TIMESTAMPTZ ); CREATE INDEX ltv_ops_doc_idx ON doc_ltv_operations(tenant_id, document_id, created_at DESC); ALTER TABLE doc_ltv_operations ENABLE ROW LEVEL SECURITY; CREATE POLICY ltv_ops_rls ON doc_ltv_operations USING (tenant_id = current_setting('auth.tenant_id')::uuid) WITH CHECK (tenant_id = current_setting('auth.tenant_id')::uuid); REVOKE UPDATE, DELETE ON doc_ltv_operations FROM cyberos_app; GRANT UPDATE (status, new_validation_data_added, new_timestamp_token, failure_reason, completed_at) ON doc_ltv_operations TO cyberos_app; ``
  1. MUST expose endpoints: ``text POST /v1/doc/documents/{id}/ltv/extend (manual extend B-T → B-LT) POST /v1/doc/documents/{id}/ltv/restamp (manual re-stamp) GET /v1/doc/documents/{id}/ltv/operations ``
  1. MUST emit 4 memory audit kinds per DEC-1805. PII per TASK-MEMORY-111: validation data + TS token hashed.
  1. MUST thread trace_id from cron / manual → fetcher → writer → audit.
  1. MUST NOT alter original signature per DEC-1804.
  1. MUST NOT skip validation data fetch before re-stamp per DEC-1800.

§2 — Why this design

Why LTV (DEC-1800)? Without embedded validation data, signature verification requires reaching OCSP/CRL/cert chain online — services may be gone in 10 years.

Why year-9 (DEC-1801)? Most TS authority certs valid 10 years; re-stamp at year-9 gives buffer.

Why fresh timestamp on re-stamp (DEC-1804)? Re-stamping with expired TS = ineffective; must use active TS authority.

Why preserve original signature (DEC-1804)? Tamper-evident — any modification = legal invalidation. We only add new layers.


§3 — API contract

POST   /v1/doc/documents/{id}/ltv/extend
POST   /v1/doc/documents/{id}/ltv/restamp
GET    /v1/doc/documents/{id}/ltv/operations

Sample operation:

{
  "operation_id": "uuid",
  "operation": "extend_bt_to_blt",
  "signature_source": "aatl",
  "original_sig_age_days": 30,
  "status": "completed",
  "new_validation_data_size_bytes": 8192,
  "new_timestamp_authority": "TSA-DigiCert"
}

§4 — Acceptance criteria

  1. B-T extended to B-LT correctly. 2. Year-9 cron scans all sigs. 3. OCSP/CRL responses embedded. 4. Cert chain embedded. 5. Fresh TS token added. 6. Original signature preserved (byte-identical). 7. ltv_operation enum cardinality 2. 8. ltv_status enum cardinality 4. 9. PAdES VRI dictionary present after extend. 10. 4 memory audit kinds emitted. 11. PII scrubbed (validation data + TS token SHA256). 12. RLS denies cross-tenant. 13. Trace_id preserved. 14. Append-only operations table via REVOKE except status cols. 15. Failure → status=failed; retry. 16. TS authority down → status=deferred; retry next cron. 17. Idempotent (multiple extends OK; each adds layer). 18. Verifiable in Adobe Reader after extend. 19. Composes with TASK-DOC-002/003/004 sigs. 20. OCSP fetch fallback to CRL on failure.

§5 — Verification

#[tokio::test]
async fn extend_adds_vri_to_pdf() {
    let ctx = TestContext::with_b_t_signed_pdf().await;
    let op = ctx.extend_ltv(ctx.doc_id).await;
    assert_eq!(op.status, "completed");
    let pdf = ctx.fetch_pdf(ctx.doc_id).await;
    assert!(ctx.parse_pades(pdf).has_vri_dictionary());
}

#[tokio::test]
async fn original_signature_preserved() {
    let ctx = TestContext::with_b_t_signed_pdf().await;
    let original_sig_bytes = ctx.extract_signature_bytes(ctx.doc_id).await;
    ctx.extend_ltv(ctx.doc_id).await;
    let post_extend_sig = ctx.extract_signature_bytes(ctx.doc_id).await;
    assert_eq!(original_sig_bytes, post_extend_sig);
}

#[tokio::test]
async fn year_9_cron_picks_up_aging_sigs() {
    let ctx = TestContext::with_sig_age_3300_days().await;
    ctx.run_ltv_cron().await;
    let op = ctx.fetch_latest_op(ctx.doc_id).await;
    assert_eq!(op.operation, "restamp_blt");
}

// 5.4..5.10

§7 — Dependencies

Upstream: TASK-DOC-002. Cross-module: TASK-DOC-003 (AATL composability), TASK-DOC-004 (VN CA composability), TASK-DOC-001 (PDF storage), TASK-MCP-007 (cron), TASK-MEMORY-111 (PII).

§10 — Failure modes

FailureDetectionOutcomeRecovery
OCSP unreachableretry, fallback CRLsev-2 auditinherent
TS authority downmark deferredretry next croninherent
Cert chain unfetchableerrorfailed; sev-1manual intervention
PDF malformedparse errfailed; sev-2manual review
Cron skippednext run catchesinherentinherent
Sig already B-LTskip extendno-opinherent
Year-9 false positivedate math checkinherentinherent
VRI dictionary write failrollbackfailedretry
Cross-tenant scanRLS0 rowsinherent
Multiple cron instancesper-tenant queueone at a timeinherent

§11 — Implementation notes


End of TASK-DOC-011 spec.