{
  "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": "96ad2c0b-be60-4715-9dd2-05a4fa3ea42d",
      "key": "ATOKEN",
      "title": "Repair API token scope and revocation boundaries",
      "field": "Security",
      "summary": "Issue scoped API tokens and make rotation, denial and revocation observable.",
      "context": "A fictional B2B export API uses long-lived tokens. Tokens copied between organizations can access too much, and revocation takes effect unpredictably.",
      "stack": [
        "TypeScript",
        "PostgreSQL",
        "REST"
      ],
      "prerequisites": [
        "Create a local synthetic API and two isolated organizations.",
        "Use generated disposable credentials only."
      ],
      "developerValue": "Practice authorization boundaries, credential lifecycle and safe diagnostics.",
      "companyValue": "Review denial paths and operational control over service access.",
      "delivery": "Ten scoped tickets across three phases. Build a synthetic local service or select a ticket after recreating its prerequisites; estimates exclude setup.",
      "phases": [
        {
          "id": "scope",
          "title": "Define token authority",
          "goal": "Separate identity, scope and safe display."
        },
        {
          "id": "lifecycle",
          "title": "Control token lifetime",
          "goal": "Rotate and revoke without widening authority."
        },
        {
          "id": "audit",
          "title": "Observe denied access",
          "goal": "Verify isolation and respond to exposure."
        }
      ],
      "tickets": [
        {
          "id": "2e70edff-9128-406a-b285-a09c2f14938e",
          "key": "ATOKEN-101",
          "title": "Define token scopes as an explicit allowlist of export operations",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "scope",
          "dependsOn": [],
          "scenario": "A token marked read-only can still trigger an export job because the handler treats every authenticated token equally.",
          "acceptanceCriteria": [
            "List exact read and create operations per scope.",
            "Unknown scopes are rejected at issuance.",
            "Protected handlers deny missing required scope."
          ],
          "implementationNotes": [
            "Do not infer permission from token naming conventions."
          ],
          "verification": [
            "Use a read scope for a permitted status request.",
            "Attempt export creation with that token and verify no job is created."
          ],
          "deliverables": [
            "Scope matrix and authorization checks"
          ],
          "rollout": "Deploy handler checks before issuing scoped tokens; disable legacy unrestricted issuance.",
          "skills": [
            "Authorization",
            "Least privilege"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 80
            },
            {
              "field": "API design",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "1d97ad59-8841-42a1-8173-a80a6d59f6e5",
          "key": "ATOKEN-102",
          "title": "Store only token verification material and a safe display prefix",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "scope",
          "dependsOn": [
            "ATOKEN-101"
          ],
          "scenario": "The token-management page retrieves complete credentials from the database every time an administrator opens it.",
          "acceptanceCriteria": [
            "Show the full token only at initial issuance.",
            "Persist one-way verification material and a nonsecret identifier.",
            "List views never return reusable token material."
          ],
          "implementationNotes": [
            "Use a mature cryptographic primitive and document verification behavior."
          ],
          "verification": [
            "Issue and authenticate a disposable token.",
            "Read the list and stored record; verify the raw token is absent."
          ],
          "deliverables": [
            "Token storage contract and disclosure tests"
          ],
          "rollout": "Migrate new tokens first; retire legacy raw-token records through explicit rotation.",
          "skills": [
            "Credential storage",
            "Privacy"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 80
            },
            {
              "field": "Database engineering",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "beb3defd-784a-43fe-9baf-d8c8cabc8d43",
          "key": "ATOKEN-103",
          "title": "Bind API token queries to the issuing organization",
          "type": "BUG",
          "priority": "URGENT",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "scope",
          "dependsOn": [
            "ATOKEN-101",
            "ATOKEN-102"
          ],
          "scenario": "An export identifier from another organization succeeds because the service checks token validity but omits tenant scope.",
          "acceptanceCriteria": [
            "Repository reads include the token organization.",
            "Cross-organization IDs receive nondisclosing denial.",
            "Authorization occurs before artifact-link creation."
          ],
          "implementationNotes": [
            "Test repository boundaries as well as routes."
          ],
          "verification": [
            "Read an export in the issuing organization.",
            "Request a second organization's export and verify no signed-link provider call."
          ],
          "deliverables": [
            "Tenant-bound repository guard"
          ],
          "rollout": "Deploy the scope guard before further token distribution; inspect denied access metadata.",
          "skills": [
            "Tenant isolation",
            "Authorization"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 70
            },
            {
              "field": "Backend",
              "percentage": 30
            }
          ],
          "patterns": []
        },
        {
          "id": "8c3f1b8f-e4b6-4508-8548-4d2c2ad8d346",
          "key": "ATOKEN-104",
          "title": "Enforce token expiration at the request authorization boundary",
          "type": "BUG",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 90,
          "phaseId": "lifecycle",
          "dependsOn": [
            "ATOKEN-102",
            "ATOKEN-103"
          ],
          "scenario": "A token expires in storage but remains usable because the cached authentication result has no expiry check.",
          "acceptanceCriteria": [
            "Check current expiry with an injected clock.",
            "Cache lifetime cannot exceed token expiry.",
            "Expired tokens fail before protected service execution."
          ],
          "implementationNotes": [
            "Use UTC instants and avoid logging presented credentials."
          ],
          "verification": [
            "Authenticate just before expiry.",
            "Advance to the exact expiry instant and deny cached and uncached requests."
          ],
          "deliverables": [
            "Expiry enforcement and clock-boundary cases"
          ],
          "rollout": "Canary with disposable short-lived tokens; flush incompatible authentication caches.",
          "skills": [
            "Authentication",
            "Temporal boundaries"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 100
            }
          ],
          "patterns": []
        },
        {
          "id": "4f334136-1c59-49fe-94ca-bea0f2afdc99",
          "key": "ATOKEN-105",
          "title": "Rotate a token with a bounded overlap window",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 240,
          "phaseId": "lifecycle",
          "dependsOn": [
            "ATOKEN-104"
          ],
          "scenario": "Customers need to replace credentials without downtime, but unrestricted overlap leaves old tokens valid indefinitely.",
          "acceptanceCriteria": [
            "Create a replacement with no broader scopes.",
            "Persist an explicit predecessor retirement deadline.",
            "Expose both token identities and overlap state safely."
          ],
          "implementationNotes": [
            "Require authorized rotation and bind it to an expected token revision."
          ],
          "verification": [
            "Rotate and authenticate both during the declared overlap.",
            "Advance beyond the overlap and deny the predecessor while accepting the replacement."
          ],
          "deliverables": [
            "Rotation command and overlap tests"
          ],
          "rollout": "Test with a synthetic client; revoke the new token if adoption fails within the window.",
          "skills": [
            "Credential rotation",
            "State transitions"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 80
            },
            {
              "field": "API design",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "49418726-207c-4c54-8c24-8a576beeab5b",
          "key": "ATOKEN-106",
          "title": "Make revocation override cached authentication results",
          "type": "TASK",
          "priority": "HIGH",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "lifecycle",
          "dependsOn": [
            "ATOKEN-104",
            "ATOKEN-105"
          ],
          "scenario": "An administrator revokes a leaked token, but one process continues accepting its cached authority.",
          "acceptanceCriteria": [
            "Define a maximum revocation propagation contract.",
            "Invalidate or version cached authority using durable token state.",
            "Fail closed when required revocation freshness cannot be established."
          ],
          "implementationNotes": [
            "Use two local consumer instances and controlled connectivity failures."
          ],
          "verification": [
            "Revoke a token and verify both consumers deny within the declared bound.",
            "Disconnect revocation freshness and verify the documented denial behavior."
          ],
          "deliverables": [
            "Revocation protocol and propagation probe"
          ],
          "rollout": "Canary two synthetic consumers; reduce cache lifetime or disable caching on propagation failure.",
          "skills": [
            "Cache consistency",
            "Revocation"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 60
            },
            {
              "field": "Distributed systems",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "a534bcc1-0472-482f-8858-ffa8e74ae57e",
          "key": "ATOKEN-107",
          "title": "Prevent a retry from issuing multiple replacement credentials",
          "type": "BUG",
          "priority": "MEDIUM",
          "difficulty": "ADVANCED",
          "estimateMinutes": 210,
          "phaseId": "lifecycle",
          "dependsOn": [
            "ATOKEN-105",
            "ATOKEN-106"
          ],
          "scenario": "The rotation response is lost and a retry creates another active successor that the customer never receives.",
          "acceptanceCriteria": [
            "Bind rotation idempotency to actor, predecessor and requested scope.",
            "One successful command creates one successor.",
            "Changed rotation parameters under the same key conflict."
          ],
          "implementationNotes": [
            "Store only a bounded issuance response under the declared secret-handling policy."
          ],
          "verification": [
            "Retry a completed rotation and count one successor.",
            "Reuse its key with broader scopes and verify rejection."
          ],
          "deliverables": [
            "Idempotent rotation transaction"
          ],
          "rollout": "Enable rotation retries with a short documented response lifetime; revoke orphan test tokens during recovery.",
          "skills": [
            "Idempotency",
            "Credential lifecycle"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 60
            },
            {
              "field": "Backend",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "9c1be7ea-24de-4749-88dc-857656a505ed",
          "key": "ATOKEN-108",
          "title": "Record denied API access without turning audit logs into a token store",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "INTERMEDIATE",
          "estimateMinutes": 150,
          "phaseId": "audit",
          "dependsOn": [
            "ATOKEN-103",
            "ATOKEN-106"
          ],
          "scenario": "Security needs failed-access context, but the existing logger captures the Authorization header and request body.",
          "acceptanceCriteria": [
            "Record safe token identity, route, reason and UTC time.",
            "Exclude authorization headers and body content.",
            "Bound repeated denial events to prevent log exhaustion."
          ],
          "implementationNotes": [
            "Use synthetic token strings in redaction tests."
          ],
          "verification": [
            "Trace a scope denial by safe token identity.",
            "Send repeated malformed tokens and verify redaction and bounded logging."
          ],
          "deliverables": [
            "Safe denial audit and rate-bound checks"
          ],
          "rollout": "Deploy audit filtering first; quarantine old diagnostic logs for authorized review.",
          "skills": [
            "Audit logging",
            "Privacy"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 50
            },
            {
              "field": "Privacy engineering",
              "percentage": 30
            },
            {
              "field": "Site reliability",
              "percentage": 20
            }
          ],
          "patterns": []
        },
        {
          "id": "4b819fcd-f964-463a-98d8-ab5b4011acee",
          "key": "ATOKEN-109",
          "title": "Rehearse credential exposure containment for one organization",
          "type": "TASK",
          "priority": "MEDIUM",
          "difficulty": "EXPERT",
          "estimateMinutes": 300,
          "phaseId": "audit",
          "dependsOn": [
            "ATOKEN-106",
            "ATOKEN-107",
            "ATOKEN-108"
          ],
          "scenario": "A fictional customer reports that a token was pasted into a public issue; operations needs a tested containment sequence.",
          "acceptanceCriteria": [
            "Identify and revoke the affected token without listing secrets.",
            "Confirm denial across every local consumer.",
            "Preserve safe audit facts and issue a scoped replacement through the normal flow."
          ],
          "implementationNotes": [
            "Use a disposable token and a fabricated incident only."
          ],
          "verification": [
            "Run the complete containment drill and verify old-token denial.",
            "Simulate an unreachable consumer and keep containment status incomplete."
          ],
          "deliverables": [
            "Exposure response runbook and executable drill"
          ],
          "rollout": "Practice in a synthetic organization; stop replacement distribution until revocation status is known.",
          "skills": [
            "Incident response",
            "Credential security"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 60
            },
            {
              "field": "Site reliability",
              "percentage": 40
            }
          ],
          "patterns": []
        },
        {
          "id": "180d9d0a-505c-48ab-8cde-6209881c01ad",
          "key": "ATOKEN-110",
          "title": "Show token last-use status without claiming it proves nonuse",
          "type": "STORY",
          "priority": "MEDIUM",
          "difficulty": "FOUNDATIONAL",
          "estimateMinutes": 75,
          "phaseId": "audit",
          "dependsOn": [
            "ATOKEN-108",
            "ATOKEN-109"
          ],
          "scenario": "Administrators interpret an empty last-used field as proof that a token was never used, despite audit ingestion gaps.",
          "acceptanceCriteria": [
            "Distinguish observed use, no recorded use and unknown coverage.",
            "State the observation window and freshness.",
            "Avoid exposing request payloads in token summaries."
          ],
          "implementationNotes": [
            "Treat last-use metadata as operational evidence with stated limits."
          ],
          "verification": [
            "Record a successful request and show its observation time.",
            "Remove audit coverage and show unknown instead of never used."
          ],
          "deliverables": [
            "Token activity projection"
          ],
          "rollout": "Publish the explicit coverage labels; revert UI wiring if scope checks fail.",
          "skills": [
            "Security UX",
            "Observability"
          ],
          "fieldMix": [
            {
              "field": "Security",
              "percentage": 70
            },
            {
              "field": "Site reliability",
              "percentage": 30
            }
          ],
          "patterns": []
        }
      ]
    }
  ]
}
