> ## Documentation Index
> Fetch the complete documentation index at: https://internal.softcrum.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Canonical Slice #1 (RECONSTRUCTION) — createInitiative: Synchronous Command Archetype

> The synchronous command archetype: a request arrives, the system validates it, changes state inside one transaction and answers with the result. Reconstructed for validation, since half the task specs declare it.

> ⚠️ **Reconstructed for validation, not recovered.** The original slice is not in this repository,
> but every task spec declares an archetype and half of them declare this one, so agents need it to
> exist. Tags: **\[derived]** is supported by the standards and ADRs we have · **\[inferred]** is
> deduced · **\[proposed]** is a gap filled with judgement.
>
> The *shape* is well evidenced — `standards/api.md`, ADR-017 and the `trackEvent` slice all
> describe it from the outside. What is genuinely uncertain is the file layout and the naming, since
> no application code exists yet to point at.

Status: **PROPOSED RECONSTRUCTION** · Coexists with [`track-event.md`](/slices/track-event) (asynchronous
pipeline archetype). Every task spec declares which one it follows (DEC-I5).

***

## What this archetype is for

A **synchronous command**: a request arrives, the system validates it, changes state, and answers
with the result. The caller waits, and the answer is authoritative — unlike the asynchronous
pipeline, where the answer is "received" and the work happens behind a queue.

Use it when the caller needs to know the outcome before proceeding: creating a record, publishing a
rule, redeeming points at a counter. Use `trackEvent` instead when the caller only needs to know the
system accepted the input.

Most of the platform is this archetype. It is the default, and the pipeline is the exception.

## The six layers

### 1. Route — `backend/api` \[derived]

```
POST /v1/{module}/{resource}
```

The route does exactly five things and no business logic:

1. Authenticate — session, API key or member token.
2. Authorize — **exactly one** declared permission, `{module}.{resource}.{action}` (R16).
3. Validate — a Zod schema over the request body, producing a typed command.
4. Resolve context — tenant, program or organization, whatever the module scopes by.
5. Call the command handler, and map its result or typed error onto the response.

Budget: Management class, p95 \<1 s. Runtime class where the caller is a machine in a hot path,
p95 \<300 ms (R18, DEC-D7).

### 2. Command handler — the module's application layer \[derived]

The handler is where the transaction lives. It is the only place in the archetype that opens one,
and it opens exactly one (R12).

```
handler(command, deps) {
  // deps come from makeDeps(ctx) — ports only, never a vendor SDK  (R1, R3)
  return db.transaction(async (tx) => {
    // 3. domain
    // 4. persistence
    // 5. outbox + audit
  })
}
```

Dependencies arrive through `makeDeps(ctx)`. A handler that imports a vendor SDK is a defect.

### 3. Domain \[derived]

Pure functions and domain services: invariants, state transitions, calculations. No I/O, no
knowledge of Drizzle, no knowledge of HTTP.

This is the layer worth being strict about. Everything above it is plumbing that can be regenerated;
the rules here are the product. **\[inferred]**

### 4. Persistence — `database/postgres` through a repository \[inferred]

Drizzle inside the transaction. Every write carries `tenant_id` and `cell_id` (R6), reaches the
database through `getDb(tenantCtx)` (R8), and obeys the data standard — parametric codes rather than
enums, amounts with their currency.

*(The repository indirection is **\[inferred]**. R8 mandates `getDb(tenantCtx)`, which could equally
be called from the handler directly. I have proposed a repository because it keeps the handler
testable without a database, but this is a place the original may differ.)*

### 5. Outbox and audit — same transaction \[derived]

Non-negotiable and the reason the transaction exists:

* One or more domain events written to the **outbox** (R13), never published directly.
* One `core.audit_log` row with a typed actor, the full old→new diff, and the `correlation_id`
  inherited from the request (R15).

If any of the three fails, all three roll back. An event describing a state change that did not
happen is worse than no event at all.

### 6. Response \[derived]

The created or updated resource, or a typed error as RFC 9457 `problem+json` with a stable `code`.
The handler returns a result type; the route maps it. A handler that formats HTTP is a handler that
cannot be called from a worker.

## What agents copy from here

* **The five-step route** and the discipline that it holds no business logic.
* **One transaction per command**, opened in the handler and nowhere else.
* **Outbox and audit inside it**, always, with the correlation id carried through.
* **Ports through `makeDeps`**, never a vendor import.
* **Typed errors** rather than thrown strings, so the route can map them without inspecting messages.
* **The domain layer stays pure**, which is what makes the tests fast enough that people write them.

## Tests the archetype requires \[inferred]

| Level       | What it proves                                                                                                                                        |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| Unit        | Domain invariants and every failure branch, with no database                                                                                          |
| Integration | The full handler against a real database: the state change, the outbox row and the audit row all commit — and an induced failure rolls all three back |
| RLS         | The command cannot touch another tenant's rows, under any input                                                                                       |
| Permission  | The route rejects a caller without its single declared permission                                                                                     |

## Where it differs from `trackEvent`

|             | createInitiative                         | trackEvent                            |
| ----------- | ---------------------------------------- | ------------------------------------- |
| Answer      | The result, authoritative                | `202 Accepted`, work pending          |
| Transaction | One, in the handler                      | One in the processor, after the queue |
| Failure     | Returned to the caller                   | Retried, then dead-lettered           |
| Idempotency | `Idempotency-Key` where the docs mark it | Always, on two fences                 |
| Budget      | p95 \<1 s Management, \<300 ms Runtime   | \<100 ms to acknowledge               |

Copying this archetype into a pipeline produces a route that does heavy work inline and blows the
ingestion budget. Copying the pipeline into a command produces a caller who never learns whether
their action succeeded. Both are review-blocking errors, which is why every task spec declares its
archetype.

## What needs validating

1. **The file layout and naming.** Route → handler → domain → repository is the shape I inferred;
   the original may name or nest these differently. **\[inferred]**
2. **Whether a repository indirection exists** or handlers call `getDb` directly. **\[inferred]**
3. **The name.** "Initiative" suggests the Tracker module's domain, which means the original slice
   probably lives in a module this repository does not contain yet. If so, this reconstruction should
   eventually be replaced by the real one rather than kept alongside it. **\[proposed]**

## Changelog

| Version | Date       | Change                                | Why                                                             | Author                 |
| ------- | ---------- | ------------------------------------- | --------------------------------------------------------------- | ---------------------- |
| 0.1.0   | 2026-08-17 | Initial reconstruction for validation | Half the task specs declare this archetype and it did not exist | daniel + claude-opus-5 |
