Skip to content

Task Specification

Every task in a Craft Easy project is driven by a spec file at tasks/<TASK-ID>/spec.md. The runner agent reads the spec before doing anything else. A high-quality spec produces a high-quality implementation.

Spec frontmatter

The spec begins with a metadata block:

**Domän:** API / Backend
**Berör:** craft-easy-api, craft-easy-admin
**Beror på:** PL-T289, PL-T293
**Risk:** HIGH | MEDIUM | LOW
**Modell:** `claude-opus-4-7`
**Spec-version:** 1
**Status:** Ready
Field Description
Domän Primary domain (API / Backend, Frontend, Mobile, Infrastructure, …)
Berör Which packages or repos are touched
Beror på BACKLOG task IDs that must be complete before this task can run
Risk HIGH = destructive migrations, auth changes, financial logic; MEDIUM = new features; LOW = docs, renames
Modell Claude model to use. See Framework Hub: Model Routing
Spec-version Increment when the spec is substantially revised after work has started
Status Draft / Ready / In Progress / Done

Spec sections

A complete spec has these sections, in order:

1. Mål (Goal)

One to two sentences: what does this task deliver and why? Written for someone who hasn't read the backlog.

2. Bakgrund (Background)

Context: what triggered this task, who is affected, how it fits the system, any tenant-specific behaviour.

3. Förundersökning (Pre-investigation)

Filled by the agent as Phase 0, before writing any code. Summary of findings, assumptions verified, discovered risks, and open questions for the owner. Uses the forundersokning.md template as a guide.

3.1 Spec-lucka-scan (mandatory first step)

A table — one row per sentence in §1–§2 plus any external spec source — where each row articulates:

Column Content
Specuttryck Exact citation from the spec
Min tolkning What the agent thinks it means
Vad jag gissar How the agent plans to implement it
Behöver svar? ja / nej — escalate ja rows to §3.4

Empty table = the task may not advance to §4. "Nothing unclear" is extremely rare — the agent should reconsider before claiming it.

The mechanism's purpose is to make tacit guesses visible. Without §3.1 the agent assumes silently and ships subtly wrong implementations.

3.2 Antaganden / 3.3 Risker / 3.4 Frågor till ägaren

Standard sections — assumptions verified by owner, identified risks, open questions with recommendations. See the template for full layout.

3.5 Berörda system

A scoping section listing the API paths, app surfaces, specs, and docs touched. Drives §13 (yt-täckningsmatris) and §14 (skapa-konsumera-par).

4. Acceptanskriterier (Acceptance Criteria)

Numbered, testable requirements. Each criterion will be signed off with a file:line reference at the end of the spec.

1. `POST /api/v1/agreements` returns 201 with the created document.
2. Existing agreements for the same tenant are not affected.
3. The admin UI shows a "New Agreement" button on the agreements list screen.

5. Datamodell (Data Model)

Exact field names, Python types, Beanie validators, defaults, indexes, TTL, soft-delete field. No vague descriptions — the agent must be able to implement without guessing.

6. Lager-trace (Layer Trace)

Field-by-field trace from database → query → model → DTO → API response → UI display. Ensures no field is lost or transformed unexpectedly.

6b. Data-flöde-trace (UI → backend)

Complement to §6 in the opposite direction, for every UI flow that sends data. Traces UI form / button → API wrapper → DTO → service → repository → DB. A single ✗ anywhere in the chain means the feature is "silently broken": the UI looks fine, the backend looks fine, but no data crosses the gap.

Classic catch this section was added to prevent: a UI that displayed "Discount code TEST −50%" applied locally, while discountCode was never serialised in the outgoing request body.

7. API-kontrakt (API Contract)

For each new or modified endpoint:

Method:   POST
Path:     /api/v1/agreements
Auth:     Bearer + require_capability("agreements.create")
Request:  { "tenant_id": str, "type": "FIPJP" | "CEP", "valid_from": date }
Response: 201 { "id": str, "created_at": datetime, ... }
Errors:   400 validation, 403 capability, 409 duplicate

8. UI-kontrakt (UI Contract)

Affected views, behaviour on success/error/loading/empty, i18n keys, responsiveness requirements.

9. Säkerhet — OWASP (Security)

Checklist for OWASP Top 10 items relevant to this task (A01 Broken Access Control, A02 Cryptographic Failures, A03 Injection, …). Mark N/A for items that genuinely do not apply.

10. Per-tenant testmatris (Per-Tenant Test Matrix)

Explicit test scenarios for each tenant configuration:

Scenario Sverige France Deutschland Cross-tenant isolation
Happy path
Missing required field ... ... ...

11. Performance budget

  • API: p95 response time ≤ 300ms (local dev, non-cold-start)
  • Frontend bundle: delta ≤ +50KB gzipped vs. current build
  • Database: new indexes declared; Cosmos Free Tier (1000 RU/s) considered

12. Accessibility (WCAG 2.1 AA)

Contrast ratio, keyboard navigation, ARIA labels, screen reader behaviour. Required for any UI change.

13. Ytäckningsmatris (Surface Coverage Matrix)

Which surfaces are affected and in which repositories:

Surface Repo Affected?
API / Backend craft-easy-api
Web portal petanque-life/apps/web
Mobile petanque-life/apps/app
Admin craft-easy-admin
Jobs craft-easy-jobs

14. Skapa-konsumera-par (Create-Consume Pairs)

Every "create" flow must have a matching "consume/display" flow and vice versa. List all pairs explicitly.

14b. Parallel-path-konsistens

A table for operations implemented in multiple places (Stripe / Swish / Invoice payment paths, per-tenant variations, alternative auth flows). Every row must either be identical or carry an explicit motivation for the divergence.

Catches: payment-path A applies a discount before tax, payment-path B applies it after, the spec says nothing about which is correct, and the test suite passes both because each path is tested in isolation.

15. Testscenario-matris (Test Scenario Matrix)

Filled BEFORE implementation (not post-hoc):

Scenario Type Expected result
Valid agreement created Happy path 201, document in DB
Duplicate agreement same tenant Edge 409
Missing type field Validation 400
Caller lacks agreements.create Authorization 403

16. Tester som måste finnas (Required Tests)

Explicit list of test files and test cases that must exist when the task is marked complete. The agent cannot mark [x] in BACKLOG.md without these passing.

17. Dokumentation

  • Which docs/ files need updating
  • Which feature/ entries need adding
  • Any public endpoint or settings change that requires reference updates

18. Definition of Done

Six-phase gate checklist. All gates must be green before marking [x] in BACKLOG.md:

Phase Gates
Fas 0 Förundersökning Section 3 filled (incl. §3.1 spec-lucka-scan); all open questions resolved or escalated
Fas 1 Build api_imports, api_lint, api_typecheck, frontend_build
Fas 2 Test api_unit, api_integration, frontend_test
Fas 3 Verify verify_changes (static analysis), verify_spec_coverage (all ACs mapped)
Fas 4 Smoke & E2E *_smoke, web_e2e, app_maestro (where applicable)
Fas 5 Tenants & Security sverige_fixture, france_fixture, deutschland_fixture, cross_tenant_isolation, pip_audit, npm_audit, secrets_scan, capability_check
Fas 6 Evidence adversarial_review, vad_testade, surface_matrix, spec_bullet_signoff, create_consume_pairs, test_scenarios

18b. Konfidens-bedömning (klar-gate)

Risk-adjusted confidence threshold the agent must clear before marking [x]:

Risk Threshold
LOW ≥ 90 %
MEDIUM ≥ 95 %
HIGH ≥ 97 % (and two independent review passes)

The agent must write a free-text statement of what the confidence is based on and what creates uncertainty. "Code looks correct" is explicitly insufficient. Checkbox-green doesn't satisfy this gate either — the gate exists exactly because checkbox-green has been wrong before.

19. Adversarial Self-Review

The agent's own adversarial pass: "If I were trying to break this, what would I try?" Must identify at least three potential attack vectors or failure modes and confirm they are handled.

19.1 Ready-to-use adversarial-review prompt

The template ships a complete Agent({...}) invocation to copy when running Fas 4. Output is saved to tasks/{TASK-ID}/review.md so it survives across runs and is part of the evidence trail.

19.2 Seven shallow-review traps

A concrete catalogue to actively scan against:

  1. Data-flow silence — UI/backend look correct in isolation; no data crosses the gap (driver for §6b)
  2. Null DI service — service registered but never wired into the consumer
  3. Missing DTO field — backend serialises a field the frontend silently ignores
  4. Parallel-path divergence — Stripe/Swish/Invoice differ in a way the spec doesn't sanction (driver for §14b)
  5. Spec-text vs code-state — spec says "must X", code does Y, tests pass because tests reflect Y
  6. Validation vs operation mismatch — input validated against schema A, operation reads schema B
  7. Too few review passes — single read-through claimed sufficient where HIGH-risk needed two independent passes

20. Vad jag faktiskt testade (What I Actually Tested)

Honest 30-second summary of what was actually run and verified. Marks: - ✓ = tested and passing - ✗ = known failure (must be documented in OWNER_TODO.md) - ⚠ = skipped with reason - 💬 = manual verification described

This section exists to prevent the agent from marking tasks complete without real verification.

21. Spec-bullet sign-off

Each acceptance criterion from section 4, mapped to the exact file and line number of the implementation:

1. POST /api/v1/agreements → 201: craft-easy-api/resources/agreements.py:47
2. Existing agreements unaffected: tests/integration/test_agreements.py:88
3. Admin "New Agreement" button: craft-easy-admin/screens/AgreementsScreen.tsx:112

Using the template

The tasks/templates/task-spec.md file in your project (synced from Framework Hub) contains the full empty template. When creating a new spec:

cp tasks/templates/task-spec.md tasks/PL-T304/spec.md

Or ask the Claude chat panel to create the spec — Opus will fill in sections based on your description of the feature.