DataTalksClub / DataTalksClub/website

Implement the versioned privacy retention registry and runner

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

Nobody has claimed this yet.

data-migration decision enhancement foundation 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 any statement below that #254/#255 alone make the retention foundation implementation-ready or that #257 may amend #254. Exact order: accepted/merged/green #254 → #281; then #255 and #283 may be delivered independently; only after both #255 and #283 are accepted/merged/green may PM replace the stale proposed design with their exact contracts and remove needs grooming. #283 is non-activating; every production retention row and protected-data execution remains disabled pending separately accepted domain/control and HUMAN gates.

Parent epic: #64
Authority/register prerequisite: #254
Privacy-kernel prerequisite: #255
Retention input prerequisite: #283
Owner direction: #23 (closed)

Product outcome

Provide a domain-neutral, policy-versioned retention registry and runner that turns only accepted #254 retention rows into deterministic dry-run plans and, after separately accepted domain adapters and controls exist, executes those exact plans in bounded, resumable, idempotent batches. The common runner pins registry/schema/adapter/input identity, fails closed on drift, unknown controls, or concurrency loss, and emits only aggregate safe evidence. Every owning domain selects and disposes its own records through its application service.

This issue has two gates. The backend foundation slice below may proceed after #254 and #255 are accepted, with every production row execution-disabled and test-only adapters. Enabling any production row is a later independently groomed domain/control phase. The foundation commit uses Refs #257; #257 retains decision and stays open while any row needed for closure is HUMAN-disabled.

Normative authority

  • _docs/PROCESS.md: role separation, versioned verification plans, safe artifacts, and Refs delivery for remaining HUMAN work.
  • _docs/specs/01-platform-architecture.md, _docs/architecture/app-boundaries.md, and _docs/architecture/shared-primitives.md: one deployment, domain-owned mutations, portable revision/idempotency, fenced durable work, and no network effect before commit.
  • _docs/specs/07-security-privacy-operations.md: approved #23 defaults, full-erasure direction, holds/exceptions, aggregate evidence, idempotent retention, and restore safety.
  • _docs/specs/09-migration-rollout-roadmap.md and _docs/specs/10-verification-strategy.md: protected-data/cutover gates, boundary/concurrency/failure evidence, and restored-backup obligations.
  • Closed #23: approved default periods, full erasure, no differential minors treatment, and the narrow already-issued real-name certificate direction.
  • #254: sole hand-edited privacy authority register, accepted policy identities, flow/domain ownership, HUMAN gates, and generated source inventory. #257 must not create a second policy authority.
  • #255: privacy app, shared authorization/audit/idempotency/operation primitives, adapter registry conventions, and jobs.DurableJob fencing.
  • #66: restore/tombstone orchestration. A retention runner is not proof that restored data remains erased.
  • #49 and future domain-adapter issues: email/Relay and all domain-specific selection, mutation, processor, and receipt behavior.

Dependency and delivery disposition

Engineering waits for accepted #254 and #255. #254 must supply an accepted canonical register version/digest and stable flow/retention-row identities; #255 must supply the accepted privacy kernel and common primitives. If the accepted #254 schema cannot express the exact executable fields below, #254 is revised and reaccepted first rather than shadowed in code.

The foundation is allowed to implement schema loading, immutable runtime definitions, common plan/run/checkpoint models, services, protocol seams, durable handlers, system checks, and synthetic tests. It registers no production retention adapter and cannot apply a production row. Every accepted-duration row initially has execution_state=disabled_missing_adapter_or_control. Enabling a row requires a new accepted #254 register version naming the production adapter contract, trigger/disposition contract, hold/exception source, owner, effective/review dates, and evidence tests; that activation goes through its own groomed domain issue and normal lifecycle.

No source-only, local, CI, staging, or deployed invocation may be represented as legal/production execution. No protected or production data may be inspected to groom, implement, test, or accept the foundation.

Sole policy source and executable registry contract

_docs/legal/privacy-authority-register.json from #254 remains the only hand-edited authority. #257 adds no hand-maintained CSV/YAML/Markdown policy table and no settings/environment override. The runtime loader selects the register's retention rows, validates them against the accepted schema, canonicalizes them, and computes a lowercase SHA-256 registry digest. Startup/system checks fail on missing, duplicate, malformed, contradictory, reordered-noncanonical, unknown-version, or unresolvable definitions.

Every retention row has these required versioned fields (added to/reaccepted in #254 if absent):

  • row_id: stable lowercase slug, never reused for changed semantics;
  • row_version: positive integer; schema_version: exactly 1 for this slice;
  • flow_id, domain_key, and positive adapter_contract_version when an adapter is named;
  • authority_ids, including closed #23 and the exact #254 authority row;
  • policy_status: accepted or human_required;
  • execution_state: disabled_missing_adapter_or_control, disabled_human_required, or later enabled; there is no runtime enable switch;
  • clock_basis: exactly utc; trigger_code; an ISO-8601 duration or schedule code; and boundary: exactly eligible when trigger_at <= evaluated_at - duration;
  • disposition_code: bounded, domain-owned accepted service contract; no free-form SQL/model/field/delete instruction;
  • hold_contract_version, exception_contract_version, and their accepted safe codes; unknown/unavailable/active controls block;
  • batch_limit in 1..1000, max_attempts in 1..100, and plan_ttl_seconds in 60..86400;
  • accepted result_codes, reason_codes, and numeric safe_count_keys only;
  • accountable domain role, policy owner, effective-date state, review-date state, source references, adapter issue, and focused test references.

An accepted duration is not enough to enable execution. A row is runnable only when policy_status=accepted, execution_state=enabled, every authority/source reference validates, effective/review state is current, and the exact registered adapter/control contracts match. human_required rows require null trigger/duration/disposition contracts and disabled_human_required; placeholders such as TBD, guessed defaults, and runtime configuration are invalid.

Rows authorized by #23, initially execution-disabled

The accepted #254 register must represent these policy facts exactly; stable row IDs may be refined only before #254 acceptance and are thereafter immutable:

  1. registrations.unverified-abuse.p14d.v1 — unverified public registrations and their abuse metadata, P14D.
  2. events.registration-pii.post-event-p90d.v1 — event registration PII, trigger after the event, P90D, subject to an accepted operational/legal-hold contract.
  3. email.website-delivery-metadata.p180d.v1 — website logical delivery intent and redacted Relay projection metadata, P180D; rendered bodies/raw provider payloads are never a website retention target.
  4. operations.security-audit-events.p365d.v1 — minimized security/audit events, P365D, preserving only separately accepted non-PII reconciliation evidence.
  5. operations.development-logs.p30d.v1 — development application logs, P30D; an external log sink requires its own adapter/control issue and cannot be mutated by a database adapter.

These rows are policy_status=accepted but remain disabled_missing_adapter_or_control in the foundation. #257 does not decide which current model fields comprise a row, invent a deletion cascade, activate an absent native event/Relay/log surface, or treat legacy Datamailer payloads as target Relay metadata. Each domain issue must map the accepted flow to exact current objects and an owning service before activation.

HUMAN-disabled rows and controls

At minimum the register keeps these disabled and non-executable until an authorized versioned decision exists:

  • educational-record active/end trigger and post-active period, including enrollment, submissions, grading, certificates, and consent evidence;
  • production application-log period;
  • Relay-owned hard-bounce/complaint suppression period and permitted website projection;
  • exact legal/security/abuse hold sources, priorities, release authority, expiry, and evidence;
  • implementation boundary for the already-issued real-name certificate exception;
  • any new retention exception, processor propagation/receipt, tombstone expiry, or restored-backup disposition.

The runner may model active, clear, expired, and unknown test outcomes, but it cannot create/release a production hold, approve an exception, select a legal disposition, or infer that missing data means clear. unknown, unavailable, stale, contradictory, or active always blocks before domain mutation.

Exact backend foundation models

All models live in privacy, use UUID primary keys where identified, bounded identifiers/codes, UTC timestamps, declarative portable constraints, and optimistic conditional updates. PostgreSQL may lock for efficiency; SQLite correctness must not depend on select_for_update.

privacy.RetentionPlan (RevisionedModel)
  • UUID; status exactly planning, ready, blocked, expired, or applied;
  • schema_version, registry_version, registry_digest;
  • immutable UTC evaluated_at, created_at, nullable expires_at, and nullable applied_at;
  • lowercase SHA-256 plan_digest and input_manifest_digest when ready;
  • required protected core.Operation of kind privacy.retention.plan;
  • bounded aggregate numeric-only safe_counts, selected-row count, and allowlisted safe reason code.

A ready plan is immutable, has at least one selected enabled row, and expires at the minimum accepted row plan TTL. Blocked/expired plans cannot apply. Applied has exactly one authoritative apply execution. Dry-run means creation of this operational plan/evidence only; it performs no domain disposition, network/provider call, or production activation.

privacy.RetentionPolicyPlan

One immutable row per selected registry row; unique (plan, row_id):

  • registry row ID/version/digest, domain key, adapter/control contract versions;
  • opaque domain_plan_ref UUID owned by the domain adapter;
  • lowercase SHA-256 input_digest and policy_plan_digest;
  • nonnegative eligible_count and bounded numeric-only safe_counts;
  • first_checkpoint_ref opaque UUID and allowlisted plan result code.

It stores no domain record ID, cursor value, PII, field name, query, serialized candidate list, reversible hash, or arbitrary adapter metadata. The domain owns any immutable candidate snapshot required to honor the plan; the common runner sees only opaque references, counts, and digests.

privacy.RetentionExecution (RevisionedModel)
  • UUID; one-to-one plan; status exactly pending, running, blocked, succeeded, or cancelled;
  • required protected core.Operation of kind privacy.retention.apply;
  • positive generation and bounded attempt count;
  • started/completed timestamps, aggregate numeric-only safe counts, result/evidence digests, and allowlisted result/error codes.

Apply requires the exact ready-plan UUID, expected revision, plan digest, idempotency key, current authorization, and a current registry/adapter/control match. Reapply of the same completed plan/key returns the original safe DTO; changed key payload/revision/digest conflicts. A plan cannot be applied by two executions.

privacy.RetentionPolicyExecution (RevisionedModel)

One per policy plan; unique (execution, policy_plan); state exactly pending, running, retry_wait, blocked, or succeeded; positive generation/attempt/max-attempt values; current checkpoint ordinal/ref/digest; numeric safe counts; result/evidence digests; allowlisted codes; next-attempt time; and protected latest DurableJob reference.

privacy.RetentionBatchCheckpoint

Append-only per policy execution and ordinal; unique (policy_execution, ordinal, generation):

  • UUID batch ID; opaque input and next checkpoint refs;
  • exact batch_limit; nonnegative selected/eligible/disposed/skipped-held/skipped-changed counts;
  • batch input/result/evidence digests;
  • state prepared, running, retry_wait, blocked, or succeeded;
  • attempt count, allowlisted result/error code, timestamps, and protected latest job reference.

A succeeded checkpoint is immutable. The next ordinal is created only after the prior checkpoint succeeds. exhausted=true is accepted only from the adapter's canonical result and completes the policy execution; zero-progress with exhausted=false, checkpoint cycles, ordinal gaps, changed batch identity, or count disagreement blocks.

privacy.RetentionPolicyFence

Exactly one row per registry row_id, with revision, active execution/policy-execution refs, positive generation, opaque lease token digest, and expiry. Acquisition/renewal/release uses conditional updates. One nonexpired fence may own a row across all plans. A stale owner, token/generation mismatch, or lost/expired fence cannot call or commit adapter success. DurableJob leases fence each batch attempt; the policy fence prevents two different runs from overlapping the same row.

Retention adapter protocol

Immutable code-registered PrivacyRetentionAdapter definitions declare domain_key, positive contract version, supported row IDs/disposition codes/control versions/safe codes, and deterministic ordering. Duplicate or conflicting registration fails system checks. No production adapter is registered in the foundation; tests use explicitly test-only fakes.

The protocol exposes:

  1. plan(context) -> RetentionDomainPlan: side-effect-free with respect to retained domain data; creates/returns an immutable domain-owned plan reference, exact input/policy-plan digests, eligible count, first checkpoint ref, and numeric safe counts for the pinned registry identity and evaluated_at.
  2. prepare_batch(context, domain_plan_ref, checkpoint_ref, limit) -> RetentionBatchPlan: side-effect-free; returns the canonical batch/checkpoint identity, selected count, input digest, and whether it is empty/exhausted.
  3. apply_batch(context, batch_plan) -> RetentionBatchResult: calls only the owning domain application service. In the same domain transaction it revalidates current eligibility plus hold/exception state for every candidate and applies only the accepted disposition. Newly eligible records not in the pinned plan wait for a later run; records changed to active/ineligible/held are skipped with safe counts, never forced.
  4. reconcile_batch(context, batch_plan) -> RetentionBatchResult: after an ambiguous crash boundary, returns the already committed result or a safe retry/block verdict before any execute retry.

Context contains only plan/execution/policy/batch UUIDs, row/registry/contract versions and digests, UTC evaluated time, generation, opaque domain-plan/checkpoint refs, job/correlation IDs, batch bound, and fence token. It contains no actor credential, PII, record locator, provider payload, free-form reason, SQL, or deletion instructions.

A domain mutation is idempotent on (policy execution UUID, generation, batch UUID, batch input digest). Adapters must make their domain result and reconciliation evidence atomic with the owning mutation. Network/provider effects are never part of apply_batch; any future processor action is a domain-owned durable intent after commit and belongs to its own accepted issue.

Plan digest, commands, and lifecycle

Canonical JSON uses sorted keys, exact ordered row IDs, canonical UTC timestamps with Z, integers only for counts, and no floats/NaN/free text. The plan digest is SHA-256 over:

schema_version, accepted registry version/digest, UTC evaluated_at, ordered selected row ID/version/digest, adapter/control contract versions, row bounds/TTL, every domain plan ref/input/policy-plan digest and eligible count, and the input-manifest digest.

It excludes database-generated plan/run IDs, creation timestamps, actor, lease/job/correlation IDs, attempt counters, and presentation formatting. The same accepted inputs therefore produce the same plan digest. A changed policy/schema/row order/adapter/control version/evaluated time/domain input digest/count changes it.

Shared services (no management/HTTP/API adapter in the foundation) expose:

  • create_dry_run(...): authorization + idempotency + exact enabled-row selection; atomically creates operation/plan/policy-plan/audit rows after every adapter plan succeeds. Any missing/disabled/unknown row, unavailable adapter/control, partial plan, unsafe output, or digest disagreement yields one blocked plan and no apply intent.
  • start_apply(plan_id, expected_revision, plan_digest, ...): revalidates unexpired plan, current registry and adapter/control definitions, every domain plan/input digest, and all row fences; atomically creates execution/policy executions, claims fences, persists versioned durable intents, completes idempotency, and wakes only after commit.
  • durable handler privacy.retention_policy.v1: processes one policy execution as sequential bounded batch jobs, renewing both leases and reporting bounded progress.
  • resume_apply(...): only from blocked/retryable state after explicit invariant recheck; creates a new generation for affected policy work and never edits a succeeded checkpoint or reuses a stale job.
  • cancel_apply(...): only before any checkpoint reaches running or succeeded; otherwise fail closed. Planning cancellation is out of scope because plans are short-lived immutable evidence.

There is no --force, arbitrary cutoff, row-ID wildcard, duration override, ignore-hold, ignore-drift, skip-adapter, raw-query, synchronous loop, or production scheduler/command. One job invocation processes at most one configured batch and chains another durable intent only after commit. The runner never holds a database transaction while planning another batch or doing network I/O.

Transactions, retries, and failure behavior

  • Reuse #255's authorization seam, core.IdempotencyRecord, core.Operation, core.AuditEvent, redaction, and jobs.DurableJob; do not create competing generic primitives.
  • Plan publication is all-or-blocked: no ready digest if any selected row failed planning. Apply start is atomic across execution rows, fences, durable intents, idempotency, operation, and audit.
  • Worker completion re-reads the plan/row/adapter/control identities, plan expiry, policy fence, durable lease, execution/checkpoint revisions, and adapter result. Drift/fence/lease/revision loss cannot commit success.
  • Explicit transient safe codes may retry within the row maximum. Permanent, unknown, unsafe, exhausted, ambiguous-after-reconcile, zero-progress, count/digest mismatch, or control unavailability blocks.
  • Crash before domain commit safely retries. Crash after domain commit/before runner commit calls reconcile_batch with the same identity. It never blindly repeats a mutation.
  • A later write cannot enter an existing plan. A planned record that becomes active/ineligible/held is skipped by domain revalidation and reported only as a count; unexplained selected/processed/skipped arithmetic blocks reconciliation.
  • Expired plan, changed registry/schema/input/adapter/control identity, newly disabled row, unknown/active hold or exception, missing checkpoint, or changed source snapshot requires a new dry-run. It is never repaired by mutating the old plan.
  • Audit action names are under privacy.retention.plan.*, privacy.retention.apply.*, privacy.retention.policy.*, and privacy.retention.batch.* with opaque targets, states/revisions, codes, counts, and digests only.

Evidence and redaction contract

Safe plan/run responses and versioned verification artifacts contain only schema/registry/plan IDs and digests, opaque plan/execution/policy/batch/job/correlation IDs, UTC evaluation/status timestamps, row IDs and contract versions, aggregate numeric counts, allowlisted codes, and pass/fail. Row IDs are policy identifiers, not record identifiers.

Never persist, log, audit, return, screenshot, or attach names, emails, usernames, IPs, raw timestamps tied to a subject, record/model primary keys, database cursors, candidate lists, reversible subject hashes, free-form values/reasons, content, message bodies, URLs, credentials/tokens/cookies, SQL, stack traces, provider payloads, or production exports. Protocol serializers reject unknown keys/types, sensitive-looking field names, unsafe strings, excessive depth/items/bytes, noncanonical Unicode/control characters, floats/NaN, and any PII/credential/provider canary; redaction alone is not acceptance.

Evidence must reconcile for each row and batch:

selected = disposed + skipped_held + skipped_changed

and totals must equal the sum of immutable succeeded checkpoints. Any other skip category or discrepancy is a blocked safe code, not a silently successful run. A zero-item plan is a valid ready dry-run only when the caller explicitly selected at least one enabled row and every row returned zero; applying it completes without domain mutation but still records the exact plan digest and evidence.

Scope now — backend foundation only

  • Extend the accepted #254 schema/validator only as required to express the exact retention rows above; do not duplicate its authority.
  • Add immutable registry loading/validation/system checks and the models, services, DTOs, adapter protocol, fences, durable handlers, audit/redaction, migrations, and internal architecture documentation above.
  • Add only test-registered synthetic adapters/control outcomes and synthetic non-PII fixtures.
  • Prove accepted-duration versus HUMAN-disabled rows, deterministic planning, apply/reconcile mechanics, bounded work, and fail-closed behavior without a production adapter, command, schedule, or protected data.

Explicit non-goals

  • No production retention adapter, model query, field mapping, delete/anonymize/overwrite, cascade, raw SQL, scheduler, cron, management command, Studio/admin/API/public route, OpenAPI, template, navigation, JavaScript, CSS, email, or notification.
  • No production/protected-data dry run or apply; no production log/provider/AWS/GitHub/Google/Slack/Datamailer/Relay call or mutation; no processor receipt or direct provider fallback.
  • No educational-record end/schedule, production-log period, suppression period, hold release rule, exception disposition, issued-certificate implementation, lawful basis, rights deadline, notice/legal wording, or policy invention.
  • No erasure request workflow, tombstone/restore fence (#66), cache/search/export invalidation, processor propagation, or claim of restore safety.
  • No domain behavior owned by accounts/#251, courses, events, email/#49, content, audit/log infrastructure, search, analytics, or future adapter issues; no cross-domain import or mutation.
  • No commit, push, merge, deployment, or external side effect outside the normal issue lifecycle.

Acceptance criteria — backend foundation slice

  • The #254 canonical register remains the sole hand-edited policy source; schema/semantic checks enforce every exact field/state/accepted/HUMAN rule above and no shadow policy table or runtime override exists.
  • The five #23 accepted-duration rows are represented exactly but execution-disabled; every unresolved educational/log/suppression/hold/exception/certificate row is human_required and disabled. No production adapter or runnable production row is registered.
  • The exact plan/policy-plan/execution/policy-execution/checkpoint/fence models and portable constraints exist; unsafe states fail on SQLite and production-like PostgreSQL.
  • Dry-run and apply share the exact canonical plan digest. Repeated identical planning is deterministic; any registry/schema/order/time/input/count/adapter/control drift changes or invalidates it.
  • Plan/apply/resume/cancel services enforce authorization, expected revision, idempotency, expiry, row enablement, adapter/control compatibility, and all-or-blocked publication/start behavior.
  • Batches are within the row limit, sequentially checkpointed, immutable after success, one per job invocation, crash/restart resumable, and reconcile after an ambiguous commit without duplicate mutation.
  • A cross-run policy fence plus durable lease prevents overlapping execution; stale/lost/expired lease, token, generation, revision, or checkpoint owners cannot call or commit an adapter result on SQLite or PostgreSQL.
  • Active/unknown/unavailable/stale holds and exceptions block; clear/expired test controls permit only the test adapter. The runner cannot create/release a hold, approve an exception, or turn missing control data into clear.
  • Before/exactly-at/after UTC boundaries, empty/one/many/late/changed candidates, newly eligible versus newly active records, zero-item plans, batch limits, apply twice, partial work, retry exhaustion, count drift, policy/input drift, and rollback all produce the specified safe result.
  • Plan/run/checkpoint/audit/job/idempotency/exception/log/test output passes PII, credential, token, URL, domain-record-ID, reversible-hash, provider-payload, free-text, Unicode/control, excessive-JSON, and NaN canaries.
  • New migrations pass forward, reverse, fresh install, migrate-back/forward (“apply twice”), constraint introspection, crash rollback, and real concurrent transaction checks on SQLite and production-like PostgreSQL; migration drift is clean.
  • Focused privacy/core/jobs/register tests, architecture import checks, 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 when the final change graph proves no render path; any actual render impact restores the graph-selected browser tier and inspected desktop/mobile screenshots.

Required verification scenarios

  1. Duplicate/missing/malformed/noncanonical rows; accepted value without authority; HUMAN value marked runnable; unknown registry/schema/adapter/control version; runtime override attempt; stale source reference; conflicting registration/startup order.
  2. The five accepted-duration definitions and every disabled HUMAN definition; requesting a disabled/missing/unknown row blocks before adapter invocation.
  3. Same inputs twice versus changed evaluation instant, registry, row order, input digest/count, adapter/control version, source snapshot, or plan expiry; recompute and compare exact plan digests.
  4. UTC before/exact/after boundaries, leap day, year/month transition, timezone-aware rejection of naive/non-UTC input, and DST-origin timestamps normalized by the owning adapter without changing the UTC contract.
  5. Empty/one/many/late candidates; candidate changes eligibility; hold added/removed/expired/unknown between plan and batch; exception mismatch; newly eligible candidates wait for the next plan.
  6. Batch sizes 1 and maximum; zero progress; final partial batch; checkpoint cycle/gap/drift; two workers, two plans for one row, stale lease/fence/generation/revision, renewal loss, and no overlapping adapter mutation.
  7. Dry-run, apply, exact replay, changed replay, apply twice, cancel before work, denied cancel after work, crash before commit, crash after domain commit/before runner commit, reconcile success/unknown, transient retry, exhaustion, permanent/unsafe failure, and resume generation fencing.
  8. Selected/disposed/skipped arithmetic, aggregate checkpoint reconciliation, unknown safe-count key/result code, excessive count/JSON, and every sensitive-output canary across protocol, persistence, audit, job, exception, log, and verification artifacts.
  9. Migration/constraint/fresh/apply-twice and true concurrent transaction scenarios on SQLite and PostgreSQL; injected rollback proves plan/execution/fence/checkpoint/job/idempotency/audit atomicity.

Browser and screenshot disposition

Expected: not_applicable. The foundation must not change a rendered route or API response. 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 any render path appears, the graph-selected Playwright tier and inspected desktop/mobile screenshots are mandatory.

Later production-row activation gate

For each production row, a separate groomed domain/control issue must name the accepted #254 register version, exact current objects and trigger clock, domain service, immutable-plan storage, hold/exception authority, adapter/control contract versions, field-level accepted disposition, batch/query bounds, migration/backfill if any, safe evidence/tests, and rollback. It passes independent tester and PM gates before a new register version can set that row enabled.

Before any production apply, an authorized HUMAN operator must separately approve the exact environment, registry/plan digest, maintenance/concurrency window, legal-hold snapshot, synthetic rehearsal, evidence destination, rollback/escalation, and maximum scope. Production dry-run/apply, protected-data access, external log/provider mutation, and release/cutover remain prohibited by this foundation and are never implied by a green test suite.

Delivery convention

After accepted #254/#255 dependencies, engineer implementation, independent tester pass, and PM acceptance of only the backend foundation, commit that slice with Refs #257; retain decision and leave #257 open. Final Closes #257 requires every row intended for production closure to have an accepted activation issue, accepted authority/control values, graph-selected verification, and authorized redacted HUMAN production-like rehearsal evidence. No push/merge 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

Engineering is blocked pending accepted #254 and #255, and the issue remains marked needs grooming. Start with _docs/PROCESS.md, the listed architecture and privacy specifications, then review the accepted register and privacy-kernel contracts from #254 and #255. Done means a separately accepted foundation with disabled production execution, validated registry identities, and the required synthetic evidence; no production row may be enabled here.

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
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.