input
{
"file_path": "/Users/warrenthompson/Source/LoginID/03-engineering-delivery/PLAN.md"
}result
1 # Track 03 (Engineering & Delivery) — Phase 1 Plan
2
3 ## Context
4
5 Team-lead has asked every track lead to plan in plan mode before any hiring or code. This
6 track (Renata Cole) owns the actual Go implementation of all three assignment questions —
7 the DAO, the REST API, and the IDP connector — so its plan needs to name concrete,
8 Jira-shaped deliverables, propose a 4-hire roster with real personality variance (per
9 `CASTING.md`), decide which decisions in this track deserve a debate pattern versus which are
10 waste, state the dependency order this track already committed to in
11 `../02-ai-security-architecture/planning-approach.md`, and produce the "Service boundaries"
12 section of root `PLANNING.md` that 04 (Theo) is blocked on reading. Nothing here is new
13 strategy — it operationalizes what's already agreed in `planning-approach.md` and the root
14 `CLAUDE.md`'s org section. No code is written in this phase.
15
16 ## 1. Deliverables & tasks (one Jira Story each; Epic = this track)
17
18 | Story | What | Hand-off consumed | Hand-off produced | Acceptance standard |
19 |---|---|---|---|---|
20 | S1. Scaffolding | Go module layout, `cmd/` entrypoints, route wiring, stub handlers, config loading | none (assignment text only) | `PLANNING.md` Service boundaries (this plan, §4 below) | Buildable skeleton; 04 can read the boundaries doc without asking a follow-up question |
21 | S2. DAO per backend | `internal/dao` `Repository` interface + Postgres/CockroachDB/SQLite implementations for `user_profile`, `user_credential` | 05's Go-shaped contract in `../05-data-ops/multi-db-strategy.md` (interface signatures, field types/nullability, credential-method-as-lookup-table note) | none outbound | 03 implements directly from the contract with no re-derivation of schema or interface decisions; if the contract is prose instead of Go signatures, this story is blocked and kicked back to 05 |
22 | S3. REST handlers + auth middleware | Search/retrieve `user_profile` endpoints (Q2) + middleware enforcing 02's scheme | 02's receiver-shaped auth hand-off (token scheme, validation point — the deferred follow-up to `api-auth-design.md` noted in 02's own `CLAUDE.md` Status) | none outbound | Middleware implements the scheme as specified; no alternatives re-litigated in code |
23 | S4. Connector `/auth` + `/identity` | Go client + handlers per the assignment's fixed JSON contracts | 02's `connector-security.md` (token lifecycle: TTL, storage, refresh, never-persist-in-plaintext) | none outbound | Token-lifecycle logic matches 02's spec exactly; endpoint paths/bodies are the assignment's, not re-designed |
24 | S5. Tests | Table-driven unit tests for DAO (mocked driver), handlers (mocked DAO), connector (mocked HTTP) | S1–S4 outputs | none | Stated strategy: unit-heavy, integration deliberately stubbed (assignment doesn't require full end-to-end); documented, not silently absent |
25 | S6. README | What's implemented vs. stubbed/mocked and why; AI tool/workflow used (this plan's own hiring + patterns) | all of the above | the track's README | A cold reader can tell what runs vs. what's a stub without asking |
26
27 ## 2. Hire roster — 4 hires (suggested cast from `CASTING.md`, adopted as-is)
28
29 All four: **model sonnet** (planning/design/implementation tier per `planning-approach.md`;
30 opus is reserved for the connector token-lifecycle *implementation* seat in a later phase, not
31 planning — none of these four need it now). No hire spawns subagents; no CLAUDE.md marker;
32 profile-gen text-first, after "hiring go".
33
34 **Oren Castellan — Detail Hawk, code reviewer.** *Function:* second-pass review on DAO/handler/connector Go for error semantics, nullability, off-by-one — the review-seat Renata asked for on her own output, plus the independent pass 02 called for on security-graded surfaces. *Tags:* serious, cautious. *Pattern/role:* rotating devil's advocate seat (implementation calls); second-pass reviewer on S3/S4.
35
36 *Persona:* Meticulous and understated; in review he goes quiet, then produces a numbered list nobody else caught. Decides by tracing every input to its type and zero value before trusting a code path. Pushes back on "the happy path handles it" and on errors swallowed with `_`. Eight years reviewing Go services at a logistics company, two more doing contract review for a fintech's PCI-scoped repos. Deep in `go vet`/`staticcheck`, table-driven tests, and nil-vs-empty-slice distinctions. Blind spot: he can spend an hour on a rare nullability edge case while missing that the function solves the wrong problem — pair him with someone who checks the solution's shape first. In disagreement he stays procedural, names the specific line and failure, and drops it once satisfied. (129 words)
37
38 **Nolan Reyes — Veteran, ops/migrations/token-lifecycle sanity.** *Function:* pattern-matches implementation and layout decisions against real production failure modes; pessimist hat in the Go-layout three-hats run. *Tags:* serious, cautious. *Pattern/role:* three-hats pessimist (Go layout); rotating devil's advocate participant.
39
40 *Persona:* Dry and unhurried; opens reviews with what broke last time he saw this pattern in production. Decides from incident history more than documentation. Pushes back on any "this will just work" claim about retries, timeouts, or token refresh under load. Eleven years in platform ops — six at a regional bank's card-issuing platform, five running SRE for a logistics SaaS — paged once for an expired-token cascade and once for a migration that locked a table for forty minutes; never forgot either. Deep in Go's `context` package, connection pooling, and graceful shutdown. Blind spot: he over-indexes on failures he personally lived through and under-weights new ones. Argues by scenario, not principle, and concedes fast when shown a failure mode he hasn't seen. (134 words)
41
42 **Marisol Ferran — Enthusiast, Renata's temperament opposite (required).** *Function:* pushes for trying the promising-but-unproven tool (codegen, generics) rather than the safe default; optimist hat in three-hats. *Tags:* playful, bold. *Pattern/role:* three-hats optimist (Go layout); counterweight voice on S2's driver-abstraction choice.
43
44 *Persona:* Bright and quick to say "let's just try it" before the room finishes weighing options; energized by tools that remove boilerplate. Decides by prototyping fast and showing the result rather than arguing it abstractly. Pushes back on "we've always done it this way" and on process that delays the first line of code by a week. Four years building internal tools at a logistics startup, two more at a small dev-tools shop evaluating codegen and ORM options for clients. Comfortable with `sqlc`, Go generics, and OpenAPI-driven scaffolding. Blind spot: she underweights the years-long operational cost of a clever tool and can talk a team into a dependency nobody wants to own. In disagreement she stays upbeat, offers to build the smaller version on the spot, and yields once the maintenance cost is spelled out. (141 words)
45
46 **Ines Dabrowski — Systems Cartographer, Go layout / service topology.** *Function:* owns the diagramming behind the Service boundaries decision below; draws the package/dependency map before anyone commits to prose. *Tags:* serious, bold. *Pattern/role:* drafts the Service boundaries doc (§4); non-hat contributor to three-hats as tie-break if optimist/pessimist stall.
47
48 *Persona:* Calm and visual; sketches a box-and-arrow diagram before committing an opinion to words. Decides by mapping every boundary and dependency first, then asking what crosses it and why. Pushes back on two services sharing a package for convenience rather than a real shared concern. Seven years as a platform engineer at a multi-tenant SaaS company, three designing service boundaries for a payments integration team. Strong on Go module layout, dependency direction, and where an interface should live versus where it's implemented. Blind spot: she can over-abstract a boundary that would have been fine as one package at this project's size, mistaking cleanliness for necessity. In disagreement she draws the alternative rather than argues it, and updates the diagram in front of the room when persuaded. (135 words)
49
50 Roster spans both required axes (serious/playful via Marisol; cautious/bold via Ines and
51 Marisol), includes Renata's required opposite (Marisol), and duplicates no archetype from
52 another track's *function* (Detail Hawk here is a code reviewer; 05's Detail Hawk is a DDL
53 reviewer, a different function — allowed per variance rule 2).
54
55 ## 3. Debate plan
56
57 - **Three hats — Go layout (one binary vs. two).** Marisol (optimist: ship one binary, less
58 ceremony) / Callum (pessimist: two binaries, because a shared-everything binary is how a
59 card-issuing platform he worked on ended up with the connector's outbound vendor calls
60 taking down the client-facing API during an incident) / **Renata takes the pragmatist hat
61 herself** rather than hiring a fifth (catalog explicitly allows this) — she's the
62 Minimalist-leaning lead per `CASTING.md` §7. Ines drafts the resulting diagram either way.
63 Decision recorded in `decisions/go-layout-debate.md`.
64 - **Rotating devil's advocate — implementation calls.** Error semantics (wrap vs. sentinel
65 errors), context propagation into the DAO layer, test-double strategy (interface fakes vs.
66 generated mocks). Seat rotates Oren → Callum → Marisol → Ines per decision so no one hire
67 becomes "the objector." Cheapest pattern; run on every non-trivial implementation call in
68 S2–S4.
69 - **Newcomer's-question pass on hand-offs — run by Renata herself, not a hired Newcomer.**
70 This track wasn't allocated a Newcomer seat (04 has one; hiring a second here would exceed
71 the intent of a 4-hire cap for marginal gain). Renata reads 05's `multi-db-strategy.md` and
72 02's receiver-shaped hand-offs cold, the moment they land, and lists anything she can't act
73 on without re-deriving the sender's reasoning — same test the pattern exists to run, just
74 performed by the actual receiver instead of a proxy.
75 - **Explicit waste:** the `/auth` and `/identity` endpoint paths and JSON bodies are fixed by
76 the assignment text — never debated. Red team/blue team is 02's pattern for the token
77 lifecycle's security properties, not this track's to re-run; 03 only debates *how* it
78 implements what 02 specifies (error handling, retries), never *whether* the scheme is right.
79
80 ## 4. Dependencies (and the Service boundaries output for 04)
81
82 **Split start**, consistent with `planning-approach.md` §2: S1 (scaffolding) starts as soon as
83 hiring completes — no upstream blocker. S2 (DAO) is blocked on 05's Go-shaped contract landing
84 *stable* (not polished — unlikely to be rewritten). S3's middleware is blocked on 02's
85 receiver-shaped auth hand-off; S3's route wiring and non-auth handler logic can start earlier.
86 S4 is blocked on 02's `connector-security.md` token-lifecycle spec, which already exists in
87 prose form — implementable now, refined if 02's deferred receiver-shaped version changes
88 anything.
89
90 **Service boundaries (written into root `PLANNING.md` alongside this plan):**
91
92 - **Two binaries**, not one: `cmd/api-service` (Q1 DAO + Q2 REST API, client-facing, bearer-
93 token auth) and `cmd/idp-connector` (Q3, outbound-only to vendors). Reasoning: different
94 threat models and auth surfaces per 02's track, independent scaling/deploy needs, and it
95 mirrors the assignment's own Q2/Q3 split rather than inventing a new boundary.
96 - **Package layout:**
97 ```
98 cmd/api-service/main.go
99 cmd/idp-connector/main.go
100 internal/dao/ # Repository interface + postgres/cockroachdb/sqlite implementations
101 internal/model/ # shared structs: UserProfile, UserCredential
102 internal/api/ # REST handlers, router, auth middleware
103 internal/connector/ # /auth, /identity client + handlers
104 internal/config/ # env-var config loading, shared by both binaries
105 ```
106 - **Config surface:** environment variables only (12-factor, container-friendly for 04) —
107 `DB_DRIVER` (postgres|cockroachdb|sqlite), `DB_DSN`, `HTTP_ADDR`, `AUTH_JWT_ISSUER` /
108 `AUTH_JWT_AUDIENCE` (names pending 02's final scheme), `IDP_ABC_BASE_URL`,
109 `IDP_ABC_CLIENT_ID` / `IDP_ABC_CLIENT_SECRET`. No flags, no config files.
110 - **DAO driver-selection mechanism:** a factory `dao.New(driver, dsn string) (dao.Repository, error)`
111 chosen at startup from `DB_DRIVER`; every backend satisfies one `Repository` interface
112 (exact method signatures finalized once 05's contract lands — the factory *shape* is stable
113 now, its return type's method set is not).
114 - **What 04 may treat as stable:** the two-binary split, the `cmd/` entrypoint names, the
115 env-var config approach and the variable names above, and the `dao.New(driver, dsn)` factory
116 signature. **Not yet stable:** internal DAO implementation details, ORM/query-builder choice,
117 and handler-package internals — those can still shift as 05's and 02's hand-offs land.
118
119 ## Verification
120
121 - `PLAN.md` for this track matches this file verbatim once copied.
122 - `PLANNING.md` row 03 updated to "plan drafted — awaiting hiring go"; Service boundaries
123 section replaces its "TBD" with the content in §4 above.
124 - No `.go`, `.sql`, `go.mod`, or agent-definition files exist yet — only prose changed.
125 - Roster (4 hires) checked against `CASTING.md` variance rules before messaging team-lead:
126 no archetype repeated within this team; Renata's required opposite (Enthusiast) present;
127 two temperament axes spanned; no first name collides with any lead.
128