Use this when you have a Boris model (or at minimum, identified bounded contexts) and need to capture detailed architecture information for each context. SNAP documents the six categories that turn a conceptual model into an actionable implementation plan: APIs, Data, External Systems/UI, Pub/Sub Events, Stories, and Risks.
Full guide: See the Architecture Discovery Workshop Playbook for the complete method.
Process
Step 1: Gather inputs
Ask the user:
- Boris model outputs — services, interactions, API candidates, and open questions. If running as part of
/architecture-discovery, these carry forward automatically. - Bounded contexts to document — all of them, or a specific subset?
- Depth — full SNAP (all 6 categories) or focused (APIs + Data + Risks only)?
- Backlog destination — should stories be pushed to Linear, Jira, Notion, or kept in markdown?
- Output destination — conversation only, Miro, Notion, or file?
Step 2: Create SNAP sheets
For each bounded context, generate a SNAP sheet by asking these questions:
APIs:
- What APIs must this context expose?
- Who are the consumers?
- What are the key operations (CRUD, search, workflow)?
Data:
- What data does this context own?
- What are the key entities and their relationships?
- What data does it NOT own but needs access to?
External Systems / UI:
- Does this context integrate with external systems?
- Does it expose a user interface?
- What protocols or standards are required?
Pub/Sub (Events):
- What events does this context publish?
- What events does it subscribe to?
- What happens if an event is missed or delayed?
Stories:
- What backlog work items emerge from this context?
- What's the first thin slice to implement?
- What spikes or investigations are needed?
Risks:
- What architectural risks exist?
- What delivery risks (skills, timeline, dependencies)?
- What unknowns need to be resolved before implementation?
Step 3: Generate SNAP sheets
Use the SNAP template to produce the deliverable:
SNAP: (Bounded Context Name)
Domain: (Parent domain) Owner: (Team or individual) Source: Boris model (date)
APIs
| API | Method | Consumer(s) | Description | Status |
|---|---|---|---|---|
| (Endpoint or operation) | GET/POST/PUT/DELETE | (Who calls it) | (What it does) | Proposed/Existing |
Data
| Entity | Key Attributes | Owned By | Accessed By | Notes |
|---|---|---|---|---|
| (Entity name) | (Key fields) | This context | (Other contexts) | (Constraints) |
External Systems / UI
| System | Integration Type | Direction | Protocol | Notes |
|---|---|---|---|---|
| (System name) | API/File/Event/UI | Inbound/Outbound/Both | REST/gRPC/File/etc. | (Details) |
Pub/Sub Events
| Event | Type | Direction | Payload Summary | Consumer(s) |
|---|---|---|---|---|
| (Event name) | Domain/Integration | Publish/Subscribe | (Key data) | (Who listens) |
Stories
| Story | Priority | Estimate | Dependencies | Notes |
|---|---|---|---|---|
| (Story title) | High/Med/Low | S/M/L | (Blockers) | (Context) |
Risks
| Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|
| (Risk description) | High/Med/Low | High/Med/Low | (Proposed mitigation) | (Who owns it) |
Repeat the template for each bounded context.
Step 4: Identify gaps
After completing all SNAP sheets, explicitly list:
- APIs referenced by consumers but not yet defined by providers
- Data claimed by multiple contexts (ownership conflicts)
- Events published but not consumed (dead letters)
- Events consumed but not published (missing producers)
- Stories with unresolved dependencies
Step 5: Generate consolidated backlog
Collect all stories from SNAP sheets into a single prioritized backlog:
| # | Story | Context | Priority | Dependencies | Notes |
|---|---|---|---|---|---|
| 1 | (Story) | (Context) | (Priority) | (Deps) | (Notes) |
Step 6: Push to backlog tool (optional)
If the user specified a backlog destination in Step 1:
- Linear — use
save_issuefor each story, with labels for the bounded context - Notion — use
notion-create-pageswith a database parent for structured backlog - Miro — use
table_createfor the consolidated backlog table - File — save to
./output/snap/(domain-name)-snap.md
Step 7: Review
Ask the user:
- Are there SNAP categories with too many unknowns?
- Should any bounded context be split further?
- Which stories should be tackled first?
- Are the risks acceptable, or do any need immediate spikes?
- Is this ready for team review, or do we need another pass?
Uncertainty Policy
| Topic | Tolerance | Action |
|---|---|---|
| API contract details (endpoints, payloads) | Low | STOP and ask — wrong contracts create integration failures |
| Data ownership per bounded context | Low | STOP and ask — ambiguous ownership causes data consistency bugs |
| Story scope and acceptance criteria | Medium | Assume + flag [ASSUMED] — stories are refined during backlog grooming |
| Risk severity and mitigation | Medium | Assume + flag [ASSUMED] — team triages during review |
| Integration event schemas | Medium | Assume + flag [ASSUMED] — schemas evolve, direction matters more |
| Story priority ordering | High | Best guess — backlog is a starting point for team discussion |
Default: STOP and ask when a topic is not listed above.
Related skills
/event-storm— first stage: discover domain events and bounded contexts/boris-model— previous stage: model service relationships/architecture-discovery— skill set that chains all three stages/story-write— flesh out individual stories from the SNAP backlog/api-docs-design— when API documentation needs to go beyond architecture contracts to developer-facing reference and guides
Output locations
| Format | Location | Notes |
|---|---|---|
| Markdown | Conversation or saved file | Always produced. Source of truth. |
| Linear | User's Linear workspace | Stories as issues via Linear MCP. |
| Notion page | User's specified Notion location | Via Notion MCP. |
| Miro table | User's specified Miro board | Via Miro MCP. |
| File | ./output/snap/(domain)-snap.md | Local file. |
Example Output
Input
- Boris model outputs: Three bounded contexts identified for Meridian Health's patient engagement platform —
Appointment Scheduling,Notifications, andPatient Identity. Key interactions: Scheduling publishesAppointmentBookedandAppointmentCancelled; Notifications subscribes to both; Patient Identity is called synchronously by Scheduling to resolve patient records. Open question: who owns preferred contact channel — Scheduling or Identity? - Bounded contexts to document: All three
- Depth: Full SNAP (all 6 categories)
- Backlog destination: Linear
- Output destination: Conversation + file saved to
./output/snap/meridian-patient-engagement-snap.md
Output (abbreviated)
SNAP: Meridian Health — Patient Engagement Platform
Boris model date: 2025-06-10
Output file: ./output/snap/meridian-patient-engagement-snap.md
SNAP: Appointment Scheduling
Domain: Patient Engagement Owner: Care Coordination Squad Source: Boris model (2025-06-10)
APIs
| API | Method | Consumer(s) | Description | Status |
|---|---|---|---|---|
/appointments | POST | Patient Portal UI, Mobile App | Book a new appointment | Proposed |
/appointments/{id} | PUT | Patient Portal UI | Reschedule or update appointment | Proposed |
/appointments/{id} | DELETE | Patient Portal UI, Call Center App | Cancel an appointment | Proposed |
/appointments?patientId= | GET | Care Coordination UI | Retrieve appointment history for a patient | Proposed |
/slots?providerId=&date= | GET | Patient Portal UI, Mobile App | Query available slots for a provider | Proposed |
Data
| Entity | Key Attributes | Owned By | Accessed By | Notes |
|---|---|---|---|---|
| Appointment | id, patientId, providerId, slotId, status, createdAt | Appointment Scheduling | Notifications (read via event) | Status enum: BOOKED, CANCELLED, COMPLETED, NO_SHOW |
| Slot | id, providerId, startTime, endTime, locationId, available | Appointment Scheduling | Patient Portal UI | Availability updated on booking/cancellation |
| Provider | id, name, specialty, locationIds | [ASSUMED] Appointment Scheduling | Care Coordination UI | May belong to a separate Staff context — flag for review |
⚠️ Ownership conflict:
preferredContactChannel(email/SMS/push) is currently unassigned. Both Scheduling and Patient Identity have a claim. Decision required before sprint 1.
External Systems / UI
| System | Integration Type | Direction | Protocol | Notes |
|---|---|---|---|---|
| Patient Portal (Web) | UI | Inbound | REST/HTTPS | Primary booking surface |
| Mobile App (iOS/Android) | UI | Inbound | REST/HTTPS | Uses same API surface as Portal |
| EHR — Cerner | API | Outbound | HL7 FHIR R4 | Slot availability and provider data sync; nightly batch + on-demand |
| Call Center App | UI | Inbound | REST/HTTPS | Read/cancel only; no booking |
Pub/Sub Events
| Event | Type | Direction | Payload Summary | Consumer(s) |
|---|---|---|---|---|
AppointmentBooked | Domain | Publish | appointmentId, patientId, providerId, slotStart, locationType | Notifications, Analytics (future) |
AppointmentCancelled | Domain | Publish | appointmentId, patientId, cancelledBy, reason, originalSlotStart | Notifications, Slot Availability (internal) |
AppointmentRescheduled | Domain | Publish | appointmentId, oldSlotStart, newSlotStart | Notifications [ASSUMED] — confirm with Notifications squad |
PatientVerified | Integration | Subscribe | patientId, identityConfirmed, preferredName | Patient Identity |
Stories
| Story | Priority | Estimate | Dependencies | Notes |
|---|---|---|---|---|
Implement POST /appointments with slot locking | High | L | Patient Identity API available | Thin slice: book, confirm, emit event |
Implement GET /slots with real-time Cerner sync | High | L | Cerner FHIR sandbox access | Spike needed first (see Risks) |
Implement cancellation flow + AppointmentCancelled event | High | M | Slot service, event bus configured | Include reason codes |
| Spike: FHIR R4 slot sync latency and rate limits | High | S | Cerner sandbox credentials | Must resolve before slot story |
| Implement appointment history endpoint | Med | S | None | Filter by date range, status |
Add AppointmentRescheduled event | Med | M | Booking + cancellation stories | Confirm payload with Notifications |
Risks
| Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|
| Cerner FHIR rate limits block real-time slot availability | High | High | Spike in sprint 1; design local cache with TTL fallback | Platform Lead |
preferredContactChannel ownership unresolved — dual-write risk | High | High | Architecture decision required before sprint 1 kickoff | Domain Architect |
| Patient Identity latency causes booking failures under load | Med | High | Async verification fallback + circuit breaker pattern [ASSUMED] | Care Coordination TL |
| EHR sandbox unavailable for dev/test | Med | Med | Mock FHIR server (HAPI) in local environment | DevOps |
SNAP: Notifications
Domain: Patient Engagement Owner: Communication Platform Squad Source: Boris model (2025-06-10)
APIs
| API | Method | Consumer(s) | Description | Status |
|---|---|---|---|---|
/notifications/preferences/{patientId} | GET/PUT | Patient Portal UI | Manage patient notification opt-ins | Proposed |
/notifications/send | POST | Internal services only | Trigger ad-hoc notification (admin use) | Proposed |
Data
| Entity | Key Attributes | Owned By | Accessed By | Notes |
|---|---|---|---|---|
| NotificationPreference | patientId, channels[], timezone, optOutAt | Notifications | Patient Portal UI | Depends on preferredContactChannel ownership resolution |
| NotificationLog | id, patientId, type, channel, sentAt, status, messageRef | Notifications | Compliance/Audit | Retention: 7 years per HIPAA |
Pub/Sub Events
| Event | Type | Direction | Payload Summary | Consumer(s) |
|---|---|---|---|---|
AppointmentBooked | Domain | Subscribe | appointmentId, patientId, slotStart | From Scheduling |
AppointmentCancelled | Domain | Subscribe | appointmentId, patientId, reason | From Scheduling |
NotificationSent | Integration | Publish | notificationId, patientId, channel, timestamp | Audit/Compliance [ASSUMED] |
⚠️
AppointmentRescheduledevent is consumed here but not yet confirmed as published by Scheduling. Flagged as missing producer.
Risks
| Risk | Likelihood | Impact | Mitigation | Owner |
|---|---|---|---|---|
| SMS delivery failures not surfaced to patient | Med | High | Implement delivery receipt webhook from Twilio; retry logic with fallback to email | Comms Platform TL |
| HIPAA PHI in notification payloads | High | High | Tokenize patientId in event payloads; retrieve PII at send time only [ASSUMED] | Security Architect |
SNAP: Patient Identity
Domain: Patient Engagement Owner: Identity & Access Squad Source: Boris model (2025-06-10)
APIs
| API | Method | Consumer(s) | Description | Status |
|---|---|---|---|---|
/patients/{id}/verify | POST | Appointment Scheduling |