1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# Codegen policy for event (crate backbone-events).
#
# `user_owned` globs are hand-written files that live inside generator-owned
# trees but are NOT schema-derived. `metaphor schema generate [--force]`
# skips them wholesale (never reads, merges, or deletes them). Everything
# else in src/ is regenerated from schema/models.
#
# Re-exports/declarations that must sit alongside generated code live inside
# `// <<< CUSTOM ... // END CUSTOM` markers (lib.rs, application/service/
# mod.rs, exports/services.rs) and are preserved by the marker mechanism,
# not listed here.
#
# Declared BEFORE any file lands (the regen-safety contract): a landing
# without the declaration is clobbered on the next regen; a declaration
# without the file is the dangling class removed by review — later seats
# extend this list on the same contract, declaring each hand file in the
# same change that lands it.
user_owned:
# The shared-audit-trail funnel (hand-written; replaces this module's
# retired per-module audit table).
- "src/infrastructure/persistence/audit.rs"
# Hand-written files the audit found undeclared; declared so a schema
# regeneration cannot delete them.
- "src/module.rs"
# The module's typed error surface (one enum, HTTP mappings) — shared by
# every hand service below.
- "src/application/service/event_error.rs"
# THE ONE seat aggregation service (EBB-1/EVM-3 replaced): state IN
# open,done AND active; 0 cap = unlimited; multi-slot x
# event_slot_count. The ONLY seat counter in the module — a second
# counter anywhere is the frozen W8 seam refusal.
- "src/application/service/seat_service.rs"
# The registration verbs: the ONE register verb (lock-first,
# count-then-insert, one transaction — SELECT ... FOR UPDATE on the
# event row, slot row too when multi-slot, INSIDE the verb), the four
# one-liner state verbs (arm rule: entering open arms the after_sub
# engines; re-confirm never re-arms), sync_from_partner (fill-only-
# when-empty), archive.
- "src/application/service/registration_service.rs"
# Event verbs: create (template-apply, once, never re-propagates), the
# typed patch whitelist (is_published/date_publish refused — the fence),
# publish/unpublish (the ONLY writers of the pair), mark_done (writes
# the first pipe_end stage by sequence), the daily done sweep verb
# (bounded batches, FOR UPDATE SKIP LOCKED claims, drives mark_done).
- "src/application/service/event_service.rs"
# Tier A capability tokens (ADR-0018): HMAC-SHA256, purpose-separated
# ("event-ics-access" expiry+rotation default; the my_tickets
# "event-registration-ticket-report-access" never-expiring DEVIATION
# documented at the mint), constant-time verify, fail-closed secret.
- "src/application/service/capability.rs"
# The /ics body builder + publication gate (uniform typed 404 for
# unpublished/archived/missing — no oracle; optionally slot-scoped under
# the SAME token).
- "src/application/service/ics_service.rs"
# The attendee ticket/badge read (responsive payloads over the API; the
# webapp renders).
- "src/application/service/my_tickets_service.rs"
# The guarded intake executor (the W8 funnel contract): typed field
# allowlist at parse (deny_unknown_fields; identity/authority columns
# NEVER admitted — no partner_id, no state, no sale_*, no active), no
# partner minting, per-identity AND per-IP fixed windows, then the ONE
# register verb.
- "src/application/service/intake_service.rs"
# The self-arming scheduler pass (ADR-0020): claim with FOR UPDATE SKIP
# LOCKED, the three engines off one row (after_sub receipts / slot
# fan-out / event cursor), receipt-truth completion (late registrants
# re-open), 'sent'=queued at enqueue, commit_per_batch with
# re-arm on overflow, typed per-scheduler failures (record ->
# continue), visible window-closed drops.
- "src/application/service/scheduler_service.rs"
# The template seam port (EVM2-2 closed): host-installed
# EventTemplateRenderer + the refusing default (unwired = typed
# template_renderer_not_composed, never a silent skip, never a
# registration blocker).
- "src/application/service/template_port.rs"
# The exported trait surface (seat availability, publication state, the
# guarded intake verb, the split's state+sale_status pair read,
# capability minting, the scheduler run verb) — the W8 seam contract.
- "src/application/service/event_surface.rs"
# The sale-order intake seam: exactly-once delivery claims through the
# seam inbox (consumer, external_id), the mint fork (zero grand total
# -> born open + armed; non-zero -> born draft held (sale, to_pay)),
# the forward-only paid heal (draft/cancel + to_pay -> open + sold +
# armed; sale_status KEPT on the cancel mirror), the one-way booth
# paid latch. The producer side (sale outbox) is host-owned.
- "src/application/service/sale_seam_service.rs"
# Booth verbs: create/patch (state, sale link, is_paid, event refused
# at patch), the confirm/release pair (release is the ONLY path back
# to available and stays human — SO-cancel never frees a booth), the
# typed delete fences (booking rows -> release first; sale link ->
# refused outright), booking lifecycle with the EBS-1 partial-unique
# wall surfaced as a typed 409 with the losing intent kept pending.
- "src/application/service/booth_command_service.rs"
# The typed lead-rule surface: the CLOSED predicate vocabulary
# (event / event_type / company / question_answer — stored domains
# banned; deny_unknown_fields DTOs), the answer-to-rule bridge, the
# rule read model (both grouping grains), and the merge-relink verb
# the host lead side calls.
- "src/application/service/lead_command_service.rs"
# The self-arming lead queue pass: claim with FOR UPDATE SKIP LOCKED,
# set-based eligible-registration walks (provenance anti-join, batch
# caps), grouping as STRATEGY (per_order for sale-linked,
# per_event_day for walk-ins), group create-vs-grow through the host
# sink, LOUD park on sink refusal (done stays false).
- "src/application/service/lead_generation_service.rs"
# The host lead sink port (create-lead / update-lead per group) + the
# refusing default (unwired host = typed park reason, never a silent
# skip). Provenance rows live here; the host lead schema is untouched.
- "src/application/service/lead_sink.rs"
# The host SMS queue port + the refusing default (unconfigured
# gateway = sms_enqueue_refused recorded, receipt unsent, row parked
# loudly — ESM-2). Rides the scheduler's channel branch, never the
# mail queue.
- "src/application/service/sms_port.rs"
# The desk scan verb (EBT-3): the FROZEN branch order — invalid ->
# canceled -> unconfirmed (no write) -> not-ongoing -> cross-event
# manual confirmation (no write) -> already-registered -> the ONE
# write (done through the transition verb). Barcode is EXACT-MATCH
# over the globally-unique column; the nomenclature machinery stays
# fenced out (register row).
- "src/application/service/desk_service.rs"
# The composer-installed request-pool shim the verb repositories resolve
# their database through (ADR-0029 pool law): hand-written, never
# schema-derived.
- "src/request_pool.rs"
# Hand repositories carrying the transactional SQL the services compose
# (services hold no raw sqlx — the DDD boundary): the seat-lock
# registration transaction (lock -> count -> insert -> arm), the
# event verbs (create + one template-apply, fence-exempt patch,
# publish/unpublish/mark_done; separate filename — the generated
# CRUD event_repository.rs keeps its own path), and the scheduler's
# SKIP LOCKED claims + receipt fan-out + receipt-truth completion.
- "src/infrastructure/persistence/seat_repository.rs"
- "src/infrastructure/persistence/event_command_repository.rs"
- "src/infrastructure/persistence/scheduler_repository.rs"
# Overlay hand repositories (same DDD boundary): the seam inbox
# claims + mint/heal/cancel-mirror SQL + booth paid latch; the booth
# verb SQL (confirm five-write, release, delete fences, the EBS-1
# pre-check demoted to nice-error under the real partial unique
# index); the lead-rule/predicate CRUD (typed rows, no stored
# domains), the self-arming request queue (SKIP LOCKED), the
# eligible-registration conjunctive SQL composed from typed
# predicates, provenance upsert/junction (idempotent), relink, and
# the events-owned catalog exclusion read.
- "src/infrastructure/persistence/sale_seam_repository.rs"
- "src/infrastructure/persistence/booth_command_repository.rs"
- "src/infrastructure/persistence/lead_command_repository.rs"
# The declared public capability tree (ics + my-tickets; the intake
# verb's router rides here too — mounted by the host only when the W8
# funnel arms). Mounted BARE of company_auth: the capability + throttle
# are the fence.
- "src/presentation/http/public_routes.rs"
# The officer tree (events/registrations/mails + generated CRUD reads).
# The host mounts it behind company_auth with the module-write gate
# keyed "event" as the innermost route layer.
- "src/presentation/http/admin_routes.rs"
# GENERATOR-DEFECT FREEZE (the website-module pattern): the pinned
# generator maps the `@default(now)` attribute to the datetime
# sentinel even when the field's type is an ENUM whose variant is
# literally named `now` (EventIntervalUnit::Now — the spec-frozen
# upstream DB value). Two arms of the one defect, each frozen at its
# generated state plus the one-line fix; unlist ONLY after the
# generator fixes the attribute-to-type arm:
# - Rust entity builders: `self.interval_unit.unwrap_or(Utc::now())`
# (E0308 — expected EventIntervalUnit).
# - SQL table DDL: `DEFAULT NOW()` on an enum column (CREATE TABLE
# refuses: "default expression is of type timestamp with time
# zone"); the fix is the enum literal `DEFAULT 'now'`.
- "src/domain/entity/mail.rs"
- "src/domain/entity/type_mail.rs"
- "migrations/20260426220005_create_mail_table.up.sql"
- "migrations/20260426220017_create_type_mail_table.up.sql"
# Hand-written DDL hardening: the EBG CHECK family (belonging, XOR,
# date orders, slot hours, default-question-reusable, per-order cap),
# the shared_blank RLS policies on events + registrations, the
# EVM2-3/EBG-1 constraint polish, and the overlay hardening (the
# EBS-1 partial unique exclusivity wall, the lead-rule/request
# uniques, the seam inbox PK).
- "migrations/*hardening*"
# The ADR-0029 tenancy strip: drops the shared_blank policies and the
# company_id columns under the ordering guard (decorator-first); the
# composing service's tenancy decorator re-declares the fence.
- "migrations/*strip_tenancy*"
# Retirement of this module's own audit table: the audited facts moved to
# the shared audit trail, so the per-module table and its closed vocabulary
# go.
- "migrations/*retire_event_audit_log*"
# The event URL shape guarantee: an external event page must carry a scheme
# and a host, the rule both the specification and the model description
# already declared as a database CHECK.
- "migrations/*event_url_scheme_check*"
# GENERATOR-DEFECT FREEZE, second arm (same pattern as 20005/20017
# above): the pinned generator numbers migration files alphabetically
# by table name, which strands four FK constraints AHEAD of the
# tables they reference (the referenced table's own migration file
# sorts later). In each frozen file the stranded FK is hand-removed
# and moved to the overlay hardening migration (20260426220040),
# which runs after every overlay table exists. Unlist ONLY after the
# generator learns dependency-ordered FK placement:
# - booth_bookings -> booths (table file sorts later at 20033)
# - lead_provenance_registrations -> lead_provenances (20035)
# - lead_provenances -> lead_rules (20038)
# - lead_rule_predicates -> lead_rules (20038)
- "migrations/20260426220031_create_booth_booking_table.up.sql"
- "migrations/20260426220031_create_booth_booking_table.down.sql"
- "migrations/20260426220034_create_lead_provenance_registration_table.up.sql"
- "migrations/20260426220034_create_lead_provenance_registration_table.down.sql"
- "migrations/20260426220035_create_lead_provenance_table.up.sql"
- "migrations/20260426220035_create_lead_provenance_table.down.sql"
- "migrations/20260426220037_create_lead_rule_predicate_table.up.sql"
- "migrations/20260426220037_create_lead_rule_predicate_table.down.sql"
# Hand-authored module documentation (root docs + the frozen build
# contract).
- "README.md"
- "SPEC.md"
- "docs/**"
# The fail-hard probe suite (fresh scratch DB on 5433,
# EVENT_TEST_ADMIN_URL override; a missing scratch Postgres panics the
# suite) — the concurrent-registration zero-oversell DoD probe, the
# /ics refusal family, the receipt re-open probe, the arm-rule probe,
# the EVM2-4 pair probe, the fence probes, mount introspection, the
# overlay families (booth exclusivity, desk branches, the sale seam,
# scheduler arming, sms overlay, transition-at-cap, CRM typed rules,
# lead-pass exclusivity).
- "tests/**"