DataTalksClub / DataTalksClub/website

Propagate privacy invalidation and record processor receipts

Open
#259 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

data-migration decision email enhancement foundation integration needs grooming operations P0 security testing
Dominant language
Python
Stars
0
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Authoritative lifecycle hold — dependency reconciliation 2026-08-30

needs grooming; engineering is not authorized. This block supersedes the implementation-ready claim and any proposal that #259 create its own propagation authority. Accepted #255, #256, #257, and audited/accepted #258 must first expose their exact merged source-action interfaces; then #282 is delivered against those identities; only after #282 is accepted/merged/green may PM rewrite #259 and remove needs grooming. #49 and applicable HUMAN/legal authority remain mandatory before any production email/processor destination or protected-data execution.

Parent epic: #64
Authority/kernel/export/retention/restore prerequisites: #254, #255, #256, #257, #258
Propagation input prerequisite: #282
Email delivery prerequisite: #49

Product outcome

Provide one domain-neutral, versioned privacy-propagation foundation that can eventually invalidate internal projections, caches, search indexes, export copies, and queued work and can record redacted reconciliation receipts from external processors. Global completion is all-or-blocked: an unknown destination, stale definition, unsafe response, ambiguous processor result, invalid rebuild, or missing receipt remains visible and never becomes success by timeout or retry.

This issue has two gates. The backend foundation below is implementation-ready only after accepted #254/#255/#256/#257/#258. It registers synthetic test destinations, adapters, and receipt verifiers only. Every production destination and every external contact remains execution-disabled until the accepted #254 register contains its exact authority, operation mapping, bounds, confirmation contract, retention, and owner. The foundation may be delivered with Refs #259; #259 retains decision and human and stays open. Production closure additionally requires accepted destination adapters, #49 for email/Relay, and the HUMAN decisions below.

Normative authority

  • _docs/PROCESS.md: role-separated lifecycle, versioned verification, safe artifacts, and Refs delivery when HUMAN work remains.
  • _docs/specs/01-platform-architecture.md, _docs/architecture/app-boundaries.md, and _docs/architecture/shared-primitives.md: one deployment, owning-domain services, atomic durable intents, after-commit network work, fenced leases, revision/idempotency, audit, and one-way imports.
  • _docs/specs/05-events-registration-email.md and #49: Relay is authoritative for delivery attempts/events and hard-bounce/complaint suppression; acceptance is not delivery; ambiguity is reconciled and never automatically resent; the website never calls SES or restores a Datamailer sender.
  • _docs/specs/06-studio-and-admin-api.md: future operator actions require capability/object/field authorization, expected revision, idempotency, confirmation, audit, and Studio/API parity. This issue adds no operator surface.
  • _docs/specs/07-security-privacy-operations.md: withdrawal, correction, restriction, objection, full erasure, processor propagation, cache/search/export cleanup, non-PII evidence, retained suppression needed to prevent harmful resend, and restored-backup fencing.
  • _docs/specs/09-migration-rollout-roadmap.md and _docs/specs/10-verification-strategy.md: protected-data/cutover gates, processor fault injection, no resurrection/resend, and graph-selected evidence.
  • Closed #23, parent #64, and #254: full erasure and approved defaults are authoritative, while processor roles/contracts/regions/transfers, lawful-basis mappings, confirmation types, deadlines, suppression disposition, receipt retention, and escalation remain HUMAN decisions.
  • #255 owns the privacy-request aggregate and domain-work kernel; #256 owns export/correction orchestration; #257 owns retention plans; #258 owns erasure-tombstone/restore-fence identities. #259 consumes their opaque identities and does not replace their state machines.

Decision and dependency boundary

The following values are not derivable from source or provider behavior and must not be invented:

  1. the accepted production destination inventory, controller/processor/subprocessor role, region/transfer/contract owner, incident contact, and review/expiry state for each destination;
  2. the exact privacy action each destination must perform, the lawful-history exception, and whether an external confirmation means accepted, applied, deleted, suppressed, unsupported, or another reviewed outcome;
  3. timeout, retry/backoff, reconciliation, callback, escalation, and requester-deadline values for each processor;
  4. the retention/expiry of non-PII receipts and confirmation references, including legal-hold and erasure interaction;
  5. the boundary between optional-processing withdrawal and transaction/security/suppression duties, including which suppression proof must remain to prevent harmful resend;
  6. authorized manual escalation and whether any processor without a machine receipt may ever be completed from independently retained evidence.

The foundation therefore enables no production destination and registers no production adapter, callback verifier, processor client, search/cache/export integration, scheduler, command, route, or startup hook. Missing decisions are represented in #254 as human_required; a production row with any missing value must use a disabled state. No environment variable, setting, database edit, plugin, command option, or runtime request can enable or weaken a row.

Sole destination authority and immutable registry

_docs/legal/privacy-authority-register.json from #254 remains the only hand-edited authority. If its accepted schema cannot express the fields below, #254 is revised and independently reaccepted first. #259 adds no shadow JSON/YAML/CSV/settings policy table.

The runtime loader selects versioned propagation destination rows, canonicalizes them, and computes one lowercase SHA-256 registry digest. Each row has:

  • stable destination_key, positive destination_version, destination class exactly internal_projection, internal_cache, internal_search, internal_export, internal_queue, or external_processor, and accountable owning domain/service;
  • #254 authority/flow/processor IDs, policy status, effective/review state, and execution state exactly disabled_human_required, disabled_missing_adapter_or_dependency, or later enabled;
  • positive adapter contract version and, for external receipts, positive receipt-verifier contract version;
  • an explicit operation map for only withdraw_optional_processing, correct, restrict, object, retention_dispose, erase, and export_expire; every entry pins the accepted source action/version, destination command code/version, safe completion codes, and rebuild rule;
  • immutable bounds: batch_limit in 1..1000, timeout_ms in 1..300000, max_attempts in 1..100, positive lease duration, ordered bounded retry delays, reconciliation deadline, escalation deadline, and receipt retention/expiry. Disabled HUMAN rows may leave undecided values null; an enabled row may not;
  • allowlisted transient, permanent, ambiguous, unsupported, and terminal result/reason codes; accepted confirmation types; callback sequence/deduplication contract where applicable; numeric safe-count keys; owner/escalation role; focused tests and evidence type.

An enabled row is runnable only when every authority and source reference validates, every decision-bearing value is present, effective/review state is current, all dependencies are accepted, and the exact immutable adapter/verifier definitions match. Duplicate/conflicting rows, unknown codes, noncanonical order, changed semantics under an existing version, unsafe bounds, or runtime override fail system checks. Test settings may register a separate synthetic manifest whose destination keys begin test_; it is never accepted as production authority.

Execution-disabled foundation models

All models live in privacy, use UUID primary keys where named, bounded identifiers/codes, UTC timestamps, portable constraints, and optimistic conditional updates. PostgreSQL locking may optimize but SQLite correctness cannot depend on select_for_update.

PrivacyPropagationOperation (RevisionedModel)
  • opaque UUID and protected core.Operation of kind privacy.propagation;
  • exact source request/work UUID, source action/version, source generation/revision, and source evidence digest from #255/#256/#257/#258;
  • pinned #254 register/schema/manifest versions and digests plus propagation-registry digest;
  • status exactly planning, ready, running, blocked, completed, or cancelled;
  • positive execution generation, selected/succeeded/blocked destination counts, numeric safe counts, bounded safe result/reason code, created/started/completed timestamps, and operation evidence digest.

One source action/generation has at most one authoritative propagation operation. ready requires one immutable work row for every required enabled destination. completed requires every required work row to have a verified safe terminal receipt for the exact generation and no destination to be missing, stale, ambiguous, blocked, or pending. blocked is non-success and may resume only through a new generation after all invariants are rechecked. Cancellation is allowed only before any destination invocation. There is no partial-complete state and no runtime skip/not-applicable inference.

PrivacyDestinationWork (RevisionedModel)

One row per selected registry destination, unique (operation, destination_key), containing pinned destination/adapter/verifier/operation-map versions and digests; immutable input/plan digests; nonnegative item count and numeric safe counts; state exactly pending, prepared, running, retry_wait, ambiguous, blocked, or succeeded; generation, attempts/max-attempts, next-attempt/reconcile/escalation timestamps; latest durable-job reference; safe result/error code; and verified result/evidence/receipt digests.

prepared and later require the exact input digest. retry_wait requires an explicit transient code and next-attempt time. ambiguous requires reconciliation and can never invoke execute again. succeeded requires an accepted receipt type and verified postcondition for the pinned action/generation. Succeeded work and its receipt identity are immutable. Unknown/missing/stale destination or adapter, unsupported action, policy drift, source-generation drift, stale fence/lease/revision, or unsafe output blocks before execution or success.

PrivacyDestinationAttempt

Append-only, unique by (destination work, generation, attempt ordinal), with opaque attempt/job/correlation UUIDs; pinned idempotency/request/input digests; started/finished timestamps; outcome exactly transient, permanent, ambiguous, confirmed, or blocked; safe code; and response/evidence digest. It stores no endpoint, locator, payload, body, credential, provider identifier, subject value, record key, or free-form error. An attempt that may have crossed an external mutation boundary but lacks an accepted receipt is ambiguous, including timeout, connection loss after submission may have begun, malformed success, or acknowledgement loss.

PrivacyProcessorReceipt

Append-only, opaque UUID keyed, and unique by destination work plus canonical receipt identity digest. It contains destination/verifier/operation-map versions; opaque processor request/operation/receipt references where policy permits; canonical receipt digest; safe state exactly accepted, confirmed_applied, confirmed_absent, confirmed_suppressed, rejected, unsupported, ambiguous, expired, or superseded; bounded safe reason code; optional monotonic sequence/version; processor-observed/received/verified/expiry timestamps; verification-key version (never the secret); and evidence digest.

accepted means only that a processor accepted work and never completes propagation. Only the exact row's HUMAN-approved safe terminal state may satisfy work. rejected, unsupported, ambiguous, expired, stale, duplicate-with-different-content, sequence regression, or unknown state blocks. Exact duplicate receipt replay returns the existing safe DTO. The same canonical receipt identity with changed content conflicts. Out-of-order receipts may advance only through the row's explicit monotonic transition map; otherwise they are retained as safe blocked evidence. Receipts are immutable after verification except that a later independently verified receipt may supersede one through an append-only link.

If processor receipt retention/expiry is unresolved, the production destination remains disabled. Expiry never converts incomplete work to success and never makes an erased or suppressed subject eligible again.

Adapter and receipt-verifier protocols

Definitions are immutable, code-registered dataclasses with deterministic enumeration. Duplicate keys with different definitions, malformed keys, unknown versions, unsafe bounds, or import-order disagreement fail system checks.

PrivacyPropagationAdapterDefinition declares destination key/version, contract version, destination class, supported operation-map versions/codes, bounds, safe result/count codes, and these methods:

  1. prepare(context) -> DestinationPlan: side-effect-free; returns exact immutable input/plan digests, selected item count, numeric safe counts, and a bounded opaque destination-plan UUID.
  2. execute(context, plan) -> DestinationResult: for an internal destination, calls only the owning domain application service; for an external processor, performs at most one fenced submission from the leased durable handler after commit. It uses the exact stable idempotency identity and returns only safe codes, counts, and digests. No network I/O occurs in the privacy/source transaction.
  3. reconcile(context, plan, attempt) -> DestinationResult: establishes the result of an ambiguous attempt without blindly repeating the mutation. It may use the separately accepted processor status/receipt interface after commit but has no send/resend method.
  4. verify_postcondition(context, result) -> DestinationVerification: proves that the pinned generation is absent/current/held as required and that later reads or rebuilds cannot reintroduce stale data. It returns counts/codes/digests only.

PrivacyProcessorReceiptVerifierDefinition declares destination/verifier contract versions, accepted receipt schema and transition map, key-version/overlap rules, replay window, and one side-effect-free canonical verification method. The method returns only the normalized safe receipt DTO above. No production verifier or callback route is registered in this foundation. Raw callbacks are authenticated and bounded by a future destination issue before this service is called; raw payloads are never persisted in #259.

Context contains only propagation/source/work/operation UUIDs, source action/generation/revision, pinned policy/manifest/destination/adapter versions and digests, destination plan UUID, execution generation, idempotency/request/input digests, job/correlation UUIDs, lease token digest, UTC bounds, and safe action codes. It contains no actor credential, PII, domain record ID, object key, cursor, endpoint, provider payload, message body, or free-form reason.

#259 registers only synthetic test adapters and a synthetic receipt verifier. It registers no accounts/courses/events/content/email/search/cache/export/queue/provider production adapter and does not absorb their domain issues.

Operation mapping and destination semantics

The source mutation is authoritative and completes through its owning #255/#256/#257/#258 service before propagation work is woken. Propagation never edits the source request/action to make a destination appear successful.

  • withdraw_optional_processing stops only future optional processing identified by the accepted row. It never rewrites lawful history, infers withdrawal for another purpose, cancels required transactional/security processing, or clears safety suppression.
  • correct invalidates or rebuilds only the accepted derived fields from the exact source revision. A destination that cannot prove the current revision is visible remains blocked.
  • restrict and object enforce only the accepted destination behavior; while policy is unresolved the row is disabled. They cannot be treated as erasure or denial by inference.
  • retention_dispose consumes the exact accepted #257 row/plan/generation and cannot widen its cutoff, candidates, disposition, or hold/exception result.
  • erase consumes the exact sealed #258 tombstone/erasure generation and must prove absence or an accepted minimum retained state. An unknown or newly applicable destination blocks completion.
  • export_expire consumes the exact #256 export/generation and must verify object/copy absence; expiry time alone is not deletion evidence.

Internal destinations must implement a generation/watermark guard in their owning read/build service before activation. Invalidating a cache key alone is insufficient: a stale fill, concurrent search build, old export, queued projection, or restored snapshot must not publish after a newer privacy generation. prepare pins the currently applicable build/input identity; the owning mutation atomically records the invalidation generation with its durable work; verify_postcondition compares the authoritative generation and destination result. A build/fill that began before invalidation must fail publication or be discarded. A later rebuild must consume the current source/tombstone/propagation fence and cannot use an old snapshot. Missing guard integration keeps that destination disabled.

For shared caches, broad cache.clear, raw key scanning, guessed key construction, and process-local-only invalidation are not accepted. For search/projection/export, deleting an old copy without fencing its builder is not accepted. For queues, cancellation/reconciliation must use the owning durable intent service and preserve ambiguity; direct row deletion is not accepted.

Idempotency, transactions, timeout, retry, and ambiguity

  • Reuse core.IdempotencyRecord, core.Operation, core.AuditEvent, revisions, and jobs.DurableJob; do not create duplicate generic primitives.
  • Creation atomically validates the exact source generation and registry, creates the operation and every required destination work row, persists one durable intent per first destination invocation, completes idempotency, and audits before after-commit wakeups. Partial plan publication creates no runnable operation.
  • The stable destination idempotency/request identity is the canonical SHA-256 over operation UUID, source action/version/generation/evidence digest, destination key/version, adapter/operation-map version, execution generation, destination plan/input digest, and bounded request options. It is reused unchanged for timeout replay/reconciliation. Same key and hash is exact replay; same key with changed content conflicts.
  • One durable handler invocation performs at most one prepare, execute, or reconcile step for one destination and never loops across destinations or batches. The handler rechecks source/policy/registry/adapter identities, revision, generation, lease, and active block before adapter invocation and again before committing a result.
  • Only an explicit transient code known to occur before any possible mutation may retry under the row's pinned attempt/backoff limit. A timeout or connection loss once invocation may have begun is ambiguous, not transient. Permanent, unsupported, unsafe, unknown, exhausted, or ambiguous-after-reconcile blocks.
  • An ambiguous work item invokes reconcile with the identical identity before any retry. It never automatically repeats execute, never changes the key to escape ambiguity, and never offers accept ambiguous, force-success, force-retry, ignore-destination, or manual receipt fabrication.
  • Callback/receipt loss is recovered by bounded reconciliation. Callback replay is authenticated/deduplicated by the future owning adapter; key rotation uses only the exact accepted overlapping verifier versions and expiry. Missing/expired/revoked/unknown verifier versions fail closed.
  • Resume is an explicit authorized, revision/idempotency-protected service call after all invariants are rechecked. It creates a new execution generation only for blocked unfinished work. Succeeded rows and old attempts/receipts remain immutable and are not rerun.

Relay, Datamailer, suppression, and provider boundary

The website never contacts SES and never adds, reactivates, or uses a Datamailer send/erase/status path for #259. Existing legacy Datamailer code and rows are inventory/migration evidence only, not a privacy propagation adapter. No processor integration may call a provider from a model hook, request transaction, callback transaction, or source-domain transaction.

The production email destination remains disabled_missing_adapter_or_dependency until #49 is accepted and integrated with an exact #254 destination row. #259 may then call only #49's redacted logical-delivery/suppression/reconciliation services. Relay remains authoritative for attempts, events, and hard-bounce/complaint suppression. The website stores no raw Relay/provider event, rendered body, recipient address, or provider suppression key.

Optional marketing withdrawal changes future eligibility only for the accepted category/purpose. It does not erase evidence or suppression that an accepted legal/safety rule requires. Hard-bounce/complaint suppression cannot be erased into renewed eligibility; if its minimum proof, retention, or erasure interaction is unresolved, the destination remains disabled and global completion remains blocked. An email intent that is pending, leased, retryable, provider-accepted, callback-lagged, ambiguous, or changed-request cannot be declared safe by #259. Reconciliation may resolve it through #49; no path submits, retries, or manually resends a message.

Authorization, receipts, evidence, and redaction

There are no HTTP, Studio, admin API, callback, or management-command adapters in this issue. Services require an injected registered authorization policy; absence is deny-by-default. Worker authorization is limited to one operation/work/generation and is rechecked from persisted state. Actor snapshots are attribution only, never authorization input.

Audits cover operation creation/start/block/resume/completion; destination prepare/execute/reconcile/postcondition; retry/exhaustion; receipt verify/replay/conflict/sequence; stale revision/lease/generation; denied attempts; and cleanup/expiry. Safe DTOs, database metadata, audits, logs, metrics, jobs, exceptions, idempotency results, receipts, and verification artifacts contain only schema/register/manifest/destination/adapter/verifier/action versions and digests; opaque operation/work/attempt/receipt/job/correlation UUIDs; UTC status timestamps and bounds; aggregate integer counts; allowlisted states/codes; and pass/fail.

Never persist, log, audit, return, screenshot, or attach names, emails, usernames, IPs, account/provider/domain IDs, raw or reversible subject hashes, subject lists, database cursors, cache keys, search queries/documents, projection/export contents or object locators, endpoints/URLs, credentials/tokens/cookies/signatures, SQL, stack traces, processor/provider payloads, Relay events, recipient/message/rendered bodies, Slack URLs, or free-form reasons. Opaque external references are retained only when #254 explicitly permits their class and retention; safe output exposes their digest, not their raw value.

Protocol serializers reject unknown keys/types, sensitive-looking names, email/URL/credential/provider canaries, free-form strings, noncanonical Unicode/control characters, floats/NaN, cycles, excessive depth/items/bytes, invalid counts, unknown safe codes, or digest mismatch. Redaction alone is not acceptance. Aggregate evidence must reconcile exactly from immutable attempts and receipts; unexplained arithmetic blocks completion.

Scope now — backend foundation only

  • Extend the accepted #254 schema/validator only as needed to represent disabled destination rows and HUMAN gates; do not duplicate policy authority.
  • Add the privacy models, constraints, migrations, registry loader, immutable definitions, DTOs, services, synthetic test adapters/verifier, durable handlers, authorization/audit/redaction integration, system checks, and internal architecture documentation above.
  • Prove deterministic all-or-blocked planning, exact idempotency, bounded retry/reconciliation, append-only receipts, generation-fenced invalidation/rebuild behavior, and fail-closed completion using synthetic non-PII data only.
  • Keep every production destination, adapter, receipt verifier, callback, scheduler, command, and route absent/disabled.

Explicit non-goals

  • No production destination inventory approval, processor/legal contract, deadline, escalation, receipt retention, suppression disposition, lawful-basis rule, requester evidence, manual override, or exception invention.
  • No production account/course/event/content/email/search/cache/export/queue/log/analytics/provider adapter, source mutation, projection rebuild, cache flush, search deletion, export deletion, job cancellation, suppression change, callback, receipt, or processor request.
  • No direct Relay/SES/Datamailer/provider path; no email send/retry/resend, no raw provider status lookup, and no claim that provider state was reconciled.
  • No production/protected-data read, dry run, migration/backfill, invalidation, erasure, correction, retention action, receipt import, or external side effect.
  • No Studio/admin API/self/accountless/public API/management command, URL, OpenAPI, template, navigation, static asset, email, notification, dashboard, alert, or runbook execution. Child 7 owns product/operator surfaces.
  • No domain behavior owned by #251/accounts, courses, events, content, email/#49, #256 exports/corrections, #257 retention, #258 restore, search/cache infrastructure, or future processor-adapter issues; no cross-domain import or direct model mutation.

Acceptance criteria — execution-disabled foundation

  • #254 remains the sole hand-edited authority. Every production destination, operation mapping, processor role/contract, timeout/retry/reconciliation/escalation deadline, confirmation type, receipt retention, suppression interaction, and owner gap is human_required or disabled; no runtime override exists.
  • The exact operation/work/attempt/receipt models, constraints, states, pinned identities, append-only/immutability rules, and all-or-blocked completion arithmetic exist and pass SQLite plus production-like PostgreSQL checks.
  • Registry/system checks reject duplicate/conflicting/noncanonical rows and definitions, missing authority, stale source/review state, unknown action/code/version, unsafe bounds, import-order disagreement, production runtime registration, and any enabled row with an unresolved value or dependency.
  • Only synthetic test_ destinations, adapters, and receipt verifier can register. Every production internal/external destination and the email/#49 destination is absent/disabled; no test path performs network/provider contact.
  • Operation planning/start/resume/cancel and destination prepare/execute/reconcile/postcondition enforce deny-by-default authorization, expected revision, exact idempotency, pinned source/policy/manifest/registry/adapter identities, atomic durable intents, and after-commit wakeups.
  • Exact replay and concurrent duplicate commands converge to one operation, one work row per required destination, one attempt identity, and one result; changed action/source generation/input/destination/version/options under the same key conflicts.
  • Only explicit pre-mutation transient failures retry within pinned bounds. Timeout/acknowledgement loss is ambiguous, reconciliation precedes any repeat, and permanent/unknown/unsupported/exhausted/ambiguous-after-reconcile outcomes block without force-success or automatic mutation replay.
  • Processor receipts are authenticated through the test verifier, canonical, append-only, replay-safe, reorder-tolerant only under the pinned transition map, expiry-aware, and unable to equate accepted with applied/completed. Missing/stale/conflicting/unsafe receipts block.
  • Synthetic internal projection/cache/search/export/queue tests prove a concurrent old build/fill/copy cannot publish after a newer privacy generation and a later rebuild consumes current source/tombstone state. Deletion without a generation guard cannot pass the adapter postcondition.
  • Withdrawal affects only the accepted future optional purpose; correction reflects the exact current source revision; restriction/objection remain policy-bound; retention consumes only its #257 plan; erasure consumes only its sealed #258 generation; export expiry verifies absence. No operation rewrites lawful history or infers another right.
  • Relay/Datamailer/suppression boundary tests prove no direct provider call or send/resend method exists, accepted is not delivered/completed, pending/in-flight/retryable/ambiguous email state blocks, and retained hard-bounce/complaint suppression cannot be cleared into renewed eligibility.
  • Audit, log, exception, job, idempotency, plan, attempt, receipt, fixture, migration, and verification output passes PII/credential/URL/cache-key/domain-ID/reversible-hash/provider-payload/message-body/free-text/Unicode/control/excessive-JSON/NaN canaries.
  • Migrations pass forward, reverse, fresh install, migrate-back/forward, constraint introspection, rollback injection, and true concurrent transaction tests on SQLite and production-like PostgreSQL; migration drift is clean.
  • Focused privacy/core/jobs/register/import/system tests, formatting/lint/type checks, container tests, and the graph-selected versioned verification plan pass using uv/Make.
  • Render contract is exactly no URL, response, template, context processor, navigation, static asset, OpenAPI, email, or browser-visible change. The independent tester records Playwright/screenshots not_applicable only if the frozen change graph proves it; any render impact restores the graph-selected browser tier and inspected desktop/mobile screenshots.

Required verification scenarios

  1. Missing/duplicate/conflicting/noncanonical destination rows; HUMAN row marked enabled; stale authority/review/dependency; adapter/verifier mismatch; unknown operation/code/version; unsafe bounds; runtime override; import-order disagreement; production registration/input rejection.
  2. Empty/one/many synthetic destinations and every structural action; missing/extra/unknown destination; changed source revision/generation/evidence; changed registry/manifest; partial plan; exact versus changed/concurrent idempotency replay.
  3. Prepare/execute/reconcile/postcondition success; crash before mutation; crash after destination commit/before kernel commit; timeout before invocation; timeout/response loss after invocation may begin; transient retry/backoff; permanent/unsupported/unsafe/unknown/exhausted failure; stale lease/fence/revision/generation; resume of only unfinished work.
  4. Receipt valid/invalid verifier, expired/revoked/unknown/overlap key version, duplicate exact/changed receipt, replayed callback identity, before/exactly-at/after replay window, out-of-order/sequence regression, accepted then confirmed, late reject, ambiguous reconciliation, missing callback, processor outage, and no raw payload persistence.
  5. Projection/search build and cache fill before/during/after correction or erasure; stale build publication race; export expiry/delete race; queue pending/in-flight/ambiguous state; restored snapshot/current-generation mismatch; newly applicable destination; deletion without rebuild guard.
  6. Optional withdrawal versus transactional/security purpose; restriction/objection unknown policy; retention plan drift/hold; erasure tombstone mismatch; lawful-history preservation; hard-bounce/complaint suppression retained; prove no eligibility renewal and no Relay/SES/Datamailer send/status fallback.
  7. Selected/succeeded/blocked and attempt/receipt arithmetic; unknown state/count key; excessive count/JSON; every sensitive-output canary across protocol, persistence, audit, logs, jobs, exceptions, migrations, and artifacts.
  8. Migration/constraint/fresh/apply-twice and true concurrent transaction scenarios on SQLite/PostgreSQL; injected rollback proves operation/work/attempt/receipt/job/idempotency/audit atomicity.

Browser and screenshot disposition

Expected for the foundation: not_applicable. It changes no route, response, template, OpenAPI document, email, or static asset. The engineer records pending_independent_tester until the independent tester recomputes the frozen change graph; only that tester may mark Playwright/screenshots not_applicable.

If a later requester/operator status surface is delivered under child 7, that separately groomed render issue must test partial, retrying, ambiguous, unsupported, blocked, escalated, and completed states; safe non-enumerating denials; keyboard/focus/status behavior; 200% reflow; private/no-store/noindex headers; and desktop 1440×900 plus mobile 390×844 screenshots under .tmp/screenshots/issue-259/ with no identity/value/provider leakage or error/debug page.

Later production-destination and HUMAN closure gate

Each production destination requires a separate groomed domain/processor issue naming the accepted #254 register version, exact owning service and source-generation guard, operation mapping, adapter/verifier versions, bounds, idempotency identity, retry/ambiguity/reconciliation rules, safe terminal receipts, suppression/retention behavior, rollback, focused tests, and owner/escalation. It passes engineer, independent tester, PM, merge, and on-call gates before a new register version can set the row enabled.

Email/Relay activation additionally requires accepted and integrated #49; it may use only #49's logical-intent/redacted-projection/reconciliation services and never direct SES, Datamailer, Relay provider events, or resend. A processor without an accepted confirmation contract remains disabled or blocked; elapsed time, operator belief, or a raw provider screenshot is not a receipt.

Before production/protected-data execution, an authorized HUMAN privacy/operator owner must approve the exact environment, register/manifest/source action and generation, destination inventory, processor contracts, operation mappings, timeout/retry/reconciliation/escalation deadlines, receipt-retention/expiry, suppression/legal-history rule, evidence destination, maintenance window, maximum scope, and rollback/escalation plan. Silence never authorizes execution or override.

[HUMAN] Using synthetic production-like data, exercise every enabled destination through success, transient, permanent, timeout, ambiguity, callback loss/replay/rotation, stale rebuild/cache fill/export copy, processor outage, partial recovery, and restored-backup boundaries. Prove that global completion requires every exact receipt/postcondition; no erased/corrected/restricted value reappears; no withdrawn purpose resumes; no safety suppression is cleared; no historical message sends; and evidence contains no PII, reversible identifier, credential, URL, provider payload, or message body.

Delivery convention

After accepted #254/#255/#256/#257/#258, engineer implementation of only the execution-disabled foundation, independent tester PASS, and PM acceptance, commit with Refs #259; retain decision and human and leave #259 open. Final Closes #259 requires every accepted-inventory production destination and adapter, accepted #49 email integration, all processor/legal/deadline/suppression/receipt decisions, and the redacted HUMAN rehearsal above. No push/merge/deploy/provider action occurs outside the orchestrator lifecycle.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with _docs/PROCESS.md, _docs/legal/privacy-authority-register.json, and the accepted interfaces from #254–#258 and #282; implementation is explicitly blocked pending dependency reconciliation and grooming. Review the specified PrivacyPropagationOperation, PrivacyDestinationWork, PrivacyDestinationAttempt, and PrivacyProcessorReceipt models, with completion defined only after the required authorities, dependencies, receipts, and human decisions are accepted.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
15/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.