{
  "policy": {
    "version": 5,
    "patterns": {
      "version": 1,
      "method": "CURATED_PRACTICE_TOPIC",
      "notice": "Pattern topics identify design choices to practice. Read the ticket's acceptance criteria and justify the simplest suitable approach. Tags are not capability or ownership evidence; an untagged ticket has no curated pattern topic assigned."
    },
    "fieldMix": {
      "version": 1,
      "method": "CURATED_ESTIMATE",
      "notice": "Field percentages are editorial estimates of the ticket's engineering focus. They total 100%; they are not measured time, proficiency scores, or ownership evidence."
    },
    "contentStatus": "PRACTICE_BRIEF",
    "assessmentStatus": "NOT_QUALIFIED",
    "evidenceUse": "NONE",
    "aiPolicy": "AI tools are welcome during implementation. Record assumptions, review the result, and verify its behavior.",
    "notice": "Fictional engineering practice briefs. Starter repositories, fixtures, automated grading, and verified ownership are not included.",
    "outcomeEvidence": "Tests, patches, and runbooks are requested deliverables. They become Outcome Evidence only through a qualified Mission and immutable Evidence IDs.",
    "ownershipEvidence": "Independent adaptation must be observed under a declared verification policy and cite immutable Evidence IDs. Completing a planning ticket establishes no Ownership Evidence."
  },
  "patternTopics": [
    {
      "id": "factory-method",
      "label": "Factory Method",
      "group": "Creational"
    },
    {
      "id": "abstract-factory",
      "label": "Abstract Factory",
      "group": "Creational"
    },
    {
      "id": "builder",
      "label": "Builder",
      "group": "Creational"
    },
    {
      "id": "prototype",
      "label": "Prototype",
      "group": "Creational"
    },
    {
      "id": "singleton",
      "label": "Singleton",
      "group": "Creational"
    },
    {
      "id": "adapter",
      "label": "Adapter",
      "group": "Structural"
    },
    {
      "id": "bridge",
      "label": "Bridge",
      "group": "Structural"
    },
    {
      "id": "composite",
      "label": "Composite",
      "group": "Structural"
    },
    {
      "id": "decorator",
      "label": "Decorator",
      "group": "Structural"
    },
    {
      "id": "facade",
      "label": "Facade",
      "group": "Structural"
    },
    {
      "id": "flyweight",
      "label": "Flyweight",
      "group": "Structural"
    },
    {
      "id": "proxy",
      "label": "Proxy",
      "group": "Structural"
    },
    {
      "id": "chain-of-responsibility",
      "label": "Chain of Responsibility",
      "group": "Behavioral"
    },
    {
      "id": "command",
      "label": "Command",
      "group": "Behavioral"
    },
    {
      "id": "interpreter",
      "label": "Interpreter",
      "group": "Behavioral"
    },
    {
      "id": "iterator",
      "label": "Iterator",
      "group": "Behavioral"
    },
    {
      "id": "mediator",
      "label": "Mediator",
      "group": "Behavioral"
    },
    {
      "id": "memento",
      "label": "Memento",
      "group": "Behavioral"
    },
    {
      "id": "observer",
      "label": "Observer",
      "group": "Behavioral"
    },
    {
      "id": "state",
      "label": "State",
      "group": "Behavioral"
    },
    {
      "id": "strategy",
      "label": "Strategy",
      "group": "Behavioral"
    },
    {
      "id": "template-method",
      "label": "Template Method",
      "group": "Behavioral"
    },
    {
      "id": "visitor",
      "label": "Visitor",
      "group": "Behavioral"
    },
    {
      "id": "ports-and-adapters",
      "label": "Ports and Adapters",
      "group": "Architectural"
    },
    {
      "id": "cqrs",
      "label": "CQRS",
      "group": "Architectural"
    },
    {
      "id": "strangler-fig",
      "label": "Strangler Fig",
      "group": "Architectural"
    },
    {
      "id": "saga",
      "label": "Saga",
      "group": "Distributed and reliability"
    },
    {
      "id": "transactional-outbox",
      "label": "Transactional Outbox",
      "group": "Distributed and reliability"
    },
    {
      "id": "circuit-breaker",
      "label": "Circuit Breaker",
      "group": "Distributed and reliability"
    },
    {
      "id": "bulkhead",
      "label": "Bulkhead",
      "group": "Distributed and reliability"
    }
  ],
  "projects": [
    {
      "id": "5a7aba25-dae9-4ba7-b408-b09d834e441f",
      "key": "RCONSENT",
      "title": "Keep communication preferences consistent across dispatch channels",
      "summary": "Version user choices, enforce purpose-specific dispatch checks and recover delayed preference updates.",
      "context": "A fictional event workspace offers optional product announcements and operational booking messages. Its product policy treats these as separate purposes. A stale audience cache currently sends optional messages after a member opts out. The brief implements fictional preference rules and makes no legal-consent certification.",
      "stack": [
        "TypeScript",
        "PostgreSQL",
        "Queue adapter",
        "Email provider double"
      ],
      "prerequisites": [
        "Create synthetic members, versioned notice text and two purpose-tagged message types.",
        "Use a fake dispatch provider with controllable queueing and acknowledgement; send no real messages."
      ],
      "developerValue": "Practice purpose modeling, versioned user choices, dispatch-time checks and consistency under retries.",
      "companyValue": "Create an inspectable preference workflow that can be reviewed against a company-approved communication policy.",
      "delivery": "Ten tickets using provider doubles and synthetic choices. No live mailing lists, legal advice or real outreach are part of the project.",
      "phases": [
        {
          "id": "choices",
          "title": "Model explicit choices",
          "goal": "Make purpose, notice version and user intent distinguishable."
        },
        {
          "id": "dispatch",
          "title": "Enforce choices at delivery",
          "goal": "Handle stale audiences and queued work with current policy checks."
        },
        {
          "id": "review",
          "title": "Review history and consistency",
          "goal": "Reconcile replicas and explain what was actually enforced."
        }
      ],
      "field": "Privacy engineering",
      "tickets": [
        {
          "id": "bf9f3515-0d28-4e3f-b32c-5fd608177db2",
          "key": "RCONSENT-101",
          "title": "Separate optional announcements from booking operations",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 60,
          "phaseId": "choices",
          "dependsOn": [],
          "scenario": "A single email-enabled flag suppresses booking confirmations when a member opts out of product announcements.",
          "acceptanceCriteria": [
            "Define separate purpose identifiers and allowed message categories.",
            "Specify defaults and unknown-purpose behavior under the fictional product policy.",
            "Keep preference evaluation explicit for each dispatch request."
          ],
          "implementationNotes": [
            "Do not infer a legal basis from a message label; the exercise uses a declared product rule."
          ],
          "verification": [
            "Evaluate announcement and booking fixtures with optional announcements disabled.",
            "Reject an unknown purpose instead of silently treating it as operational."
          ],
          "deliverables": [
            "Purpose registry and preference truth table"
          ],
          "rollout": "Introduce purpose tags before migrating existing preference checks.",
          "skills": [
            "Domain modeling",
            "Policy evaluation"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 80
            },
            {
              "field": "Backend",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "764d8d1f-e8f3-46bf-b491-0b4da9a84521",
          "key": "RCONSENT-102",
          "title": "Record the notice version shown when a preference changes",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 120,
          "phaseId": "choices",
          "dependsOn": [
            "RCONSENT-101"
          ],
          "scenario": "The database stores only the latest boolean, so support cannot tell which choice text the member saw.",
          "acceptanceCriteria": [
            "Append subject, purpose, choice, UTC instant and notice version for each accepted change.",
            "Preserve the prior event and derive current state deterministically.",
            "Reject unknown notice versions and keep notice content immutable once referenced.",
            "Derive the subject from authenticated authority and enforce subject/tenant authorization for preference mutations at the repository boundary."
          ],
          "implementationNotes": [
            "Use bounded metadata; do not collect device fingerprints or unrelated browsing history to record a choice."
          ],
          "verification": [
            "Change a preference twice under two published notice versions and inspect the retained events.",
            "Submit an unknown version and verify no state change or append.",
            "Attempt a foreign subject and a foreign tenant through the mutation boundary; verify denial with no preference state change or appended event."
          ],
          "deliverables": [
            "Versioned preference events and immutable notice fixtures"
          ],
          "rollout": "Publish notice versions before accepting their changes; corrections create new versions.",
          "skills": [
            "Event history",
            "Versioning"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 50
            },
            {
              "field": "Data engineering",
              "percentage": 30
            },
            {
              "field": "Security",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "750a64f0-3ba2-447b-b9d4-d61ee3eff84c",
          "key": "RCONSENT-103",
          "title": "Make the preference form submit the user’s explicit final choice",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 120,
          "phaseId": "choices",
          "dependsOn": [
            "RCONSENT-102"
          ],
          "scenario": "An autosave race restores a checked box after the user turns it off and navigates away.",
          "acceptanceCriteria": [
            "Represent pending, saved and failed states without presenting an unconfirmed value as saved.",
            "Use version-aware updates so an older response cannot overwrite a newer choice.",
            "Keep controls keyboard-operable and associate errors with the affected purpose."
          ],
          "implementationNotes": [
            "Do not use preselected optional choices or obscured controls as a substitute for the declared interaction contract."
          ],
          "verification": [
            "Complete two opposite updates out of order and verify the latest accepted choice appears.",
            "Fail a save and navigate back; the form must distinguish persisted state from the unsaved attempt."
          ],
          "deliverables": [
            "Preference form state and out-of-order response tests"
          ],
          "rollout": "Deploy with the versioned API; reverting the UI must not rewrite stored preference events.",
          "skills": [
            "Form state",
            "Accessible interaction"
          ],
          "fieldMix": [
            {
              "field": "Frontend",
              "percentage": 40
            },
            {
              "field": "Privacy engineering",
              "percentage": 30
            },
            {
              "field": "Accessibility",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "7f253f55-67c7-4d35-8514-9055f61e44bd",
          "key": "RCONSENT-104",
          "title": "Recheck optional-message eligibility immediately before provider dispatch",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "dispatch",
          "dependsOn": [
            "RCONSENT-101",
            "RCONSENT-102"
          ],
          "scenario": "An audience list was built yesterday. A member who opted out this morning still receives the queued announcement.",
          "acceptanceCriteria": [
            "Evaluate current purpose-specific preference at the dispatch boundary.",
            "Suppress ineligible work with a recorded safe reason and no provider call.",
            "Define behavior when preference state is unavailable; optional delivery must not assume permission from a stale list."
          ],
          "implementationNotes": [
            "The audience snapshot is planning input, not final dispatch authority."
          ],
          "verification": [
            "Queue while enabled, opt out, then release the job and verify no provider request.",
            "Make the preference repository unavailable and verify the declared hold/suppression path without sending."
          ],
          "deliverables": [
            "Dispatch guard and stale-audience regressions"
          ],
          "rollout": "Deploy the guard before replaying old queue entries; monitor bounded suppression categories.",
          "skills": [
            "Authorization timing",
            "Queue processing"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 50
            },
            {
              "field": "Security",
              "percentage": 30
            },
            {
              "field": "Platform engineering",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "92a73782-0f41-4a1e-8468-fc0736fde413",
          "key": "RCONSENT-105",
          "title": "Bind a queued announcement to its purpose and content revision",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 180,
          "phaseId": "dispatch",
          "dependsOn": [
            "RCONSENT-101",
            "RCONSENT-104"
          ],
          "scenario": "An operator edits a queued campaign from a booking reminder into promotional content while retaining the original operational tag.",
          "acceptanceCriteria": [
            "Freeze purpose and content revision for each queued delivery request.",
            "Require a new reviewed request when a material content/purpose change occurs.",
            "Reject dispatch when the referenced purpose or content revision cannot be resolved."
          ],
          "implementationNotes": [
            "Use synthetic content and a local review state; this ticket sends nothing outside the provider double."
          ],
          "verification": [
            "Edit the source campaign after queueing and verify the queued revision remains identifiable.",
            "Attempt to retag optional content as operational through a mutable field and verify the request is rejected."
          ],
          "deliverables": [
            "Immutable dispatch request contract and revision tests"
          ],
          "rollout": "Version the queue payload and hold unresolved legacy jobs for explicit conversion.",
          "skills": [
            "Immutable inputs",
            "Purpose limitation"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 60
            },
            {
              "field": "Data engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "3588ccaf-5c6a-418b-8f6b-9a1e1a2d8d9e",
          "key": "RCONSENT-106",
          "title": "Stop an opt-out retry from being lost behind an older opt-in event",
          "type": "BUG",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "dispatch",
          "dependsOn": [
            "RCONSENT-102",
            "RCONSENT-104"
          ],
          "scenario": "Preference events reach a delivery replica out of order. A delayed older opt-in restores eligibility after a newer opt-out.",
          "acceptanceCriteria": [
            "Apply a subject/purpose ordering rule with comparable revisions.",
            "Ignore older duplicates while preserving their receipt for bounded diagnosis.",
            "Expose replica freshness and define dispatch behavior when current ordering cannot be established."
          ],
          "implementationNotes": [
            "Wall-clock arrival order is not a reliable source revision; document the authority issuing revisions."
          ],
          "verification": [
            "Deliver opt-out, then older opt-in, then duplicate opt-out and verify current state remains disabled.",
            "Create a missing-revision gap and verify optional dispatch follows the declared fail-closed or authoritative-read path."
          ],
          "deliverables": [
            "Replica ordering protocol and event permutation tests"
          ],
          "rollout": "Canary replica reads with authoritative comparisons; disable replica-based optional dispatch if gaps cannot be resolved.",
          "skills": [
            "Event ordering",
            "Consistency"
          ],
          "fieldMix": [
            {
              "field": "Distributed systems",
              "percentage": 60
            },
            {
              "field": "Privacy engineering",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "d75a61ce-6f11-4c53-a9e2-9156e7143965",
          "key": "RCONSENT-107",
          "title": "Explain which queued messages an opt-out can still prevent",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 180,
          "phaseId": "review",
          "dependsOn": [
            "RCONSENT-103",
            "RCONSENT-104",
            "RCONSENT-105"
          ],
          "scenario": "The settings page promises instant cancellation even when the provider has already accepted a message that cannot be recalled.",
          "acceptanceCriteria": [
            "Define queued, dispatching, provider-accepted and completed boundaries.",
            "Describe prevention guarantees in user-facing copy consistent with those states.",
            "Cancel controllable work and report when a provider-accepted message is beyond the supported recall boundary."
          ],
          "implementationNotes": [
            "Do not claim that recording a preference change reverses an already completed delivery."
          ],
          "verification": [
            "Opt out at each controlled boundary and compare provider calls with displayed status.",
            "Simulate a provider without recall support and verify the interface does not show a false cancellation success."
          ],
          "deliverables": [
            "Cancellation state contract and truthful settings copy"
          ],
          "rollout": "Publish the clarified contract with the dispatch guard; preserve accepted-delivery history under the declared retention policy.",
          "skills": [
            "State semantics",
            "Product communication"
          ],
          "fieldMix": [
            {
              "field": "Privacy engineering",
              "percentage": 60
            },
            {
              "field": "Integrations",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "dfc34299-dab1-4af3-9c5f-b2ac3e76b6ab",
          "key": "RCONSENT-108",
          "title": "Expose preference history only to its subject and scoped support role",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "review",
          "dependsOn": [
            "RCONSENT-102",
            "RCONSENT-107"
          ],
          "scenario": "A support page returns all members’ preference histories after checking only that the requester has any staff role.",
          "acceptanceCriteria": [
            "Apply subject or tenant-scoped support authorization at the repository boundary.",
            "Return purpose, choice, notice version and time without unrelated contact details.",
            "Audit privileged history access using safe identifiers and bounded reason categories."
          ],
          "implementationNotes": [
            "An audit event records access, not an inference about why a person made their choice."
          ],
          "verification": [
            "Read the matching subject’s history and an authorized support fixture.",
            "Attempt a foreign-tenant subject and an unscoped staff role; verify denial and no history leakage."
          ],
          "deliverables": [
            "Scoped history endpoint and access regressions"
          ],
          "rollout": "Enable the history view after repository-level checks pass; keep analytics separate from preference content.",
          "skills": [
            "Access control",
            "Minimal disclosure"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 50
            },
            {
              "field": "Privacy engineering",
              "percentage": 50
            }
          ],
          "patterns": []
        },
        {
          "id": "d441dfe4-aa51-43d0-b7f0-290b45163fb0",
          "key": "RCONSENT-109",
          "title": "Reconcile audience caches without restoring old optional choices",
          "type": "CHORE",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "review",
          "dependsOn": [
            "RCONSENT-104",
            "RCONSENT-106"
          ],
          "scenario": "A nightly audience rebuild copies an old export over the current preference cache.",
          "acceptanceCriteria": [
            "Bind rebuild inputs to a declared cutoff and subject/purpose revisions.",
            "Prevent rebuild writes from replacing newer authoritative or replicated choices.",
            "Report missing and contradictory inputs as reconciliation exceptions."
          ],
          "implementationNotes": [
            "Treat audience caches as derived state; preserve current choice authority outside the rebuild."
          ],
          "verification": [
            "Run a rebuild while a member opts out and verify the newer revision wins.",
            "Feed contradictory same-revision values and verify the rebuild stops or quarantines them without guessing."
          ],
          "deliverables": [
            "Audience reconciliation and concurrent-choice tests"
          ],
          "rollout": "Build into a new cache generation and switch only after consistency checks; retain the prior generation for diagnosis.",
          "skills": [
            "Cache reconciliation",
            "Conflict handling"
          ],
          "fieldMix": [
            {
              "field": "Distributed systems",
              "percentage": 40
            },
            {
              "field": "Privacy engineering",
              "percentage": 40
            },
            {
              "field": "Data engineering",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "91ae98b2-019e-4078-9c93-a2d73d4d4271",
          "key": "RCONSENT-110",
          "title": "Rehearse preference enforcement from settings through provider acknowledgement",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "EXPERT",
          "estimateMinutes": 270,
          "phaseId": "review",
          "dependsOn": [
            "RCONSENT-103",
            "RCONSENT-105",
            "RCONSENT-106",
            "RCONSENT-107",
            "RCONSENT-108",
            "RCONSENT-109"
          ],
          "scenario": "Unit tests cover the checkbox and worker separately, but not a user changing a preference while replicas lag and provider requests are in flight.",
          "acceptanceCriteria": [
            "Run a deterministic end-to-end matrix of opt-in/out, replica delay, queued work and provider acknowledgement.",
            "Reconcile every provider request with the exact purpose, content and evaluated preference revisions.",
            "Report tested conditions and unavoidable in-flight limits without claiming legal consent compliance."
          ],
          "implementationNotes": [
            "All deliveries terminate at a fake provider; the exercise never sends messages to real recipients."
          ],
          "verification": [
            "Exercise out-of-order events and opt-out at each dispatch boundary.",
            "Fail preference lookup and provider acknowledgement separately, then verify retries cannot send an ineligible optional message."
          ],
          "deliverables": [
            "Preference-enforcement rehearsal and decision trace"
          ],
          "rollout": "Enable the full synthetic workflow only after the matrix passes; hold optional dispatch when authority or revision consistency is unresolved.",
          "skills": [
            "Workflow testing",
            "Policy enforcement"
          ],
          "fieldMix": [
            {
              "field": "Quality engineering",
              "percentage": 40
            },
            {
              "field": "Privacy engineering",
              "percentage": 40
            },
            {
              "field": "Integrations",
              "percentage": 20
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
