MAP-UI-001: Template to FEAT Wiring Map
| Reference Number | Version | Effective Date | Supersedes | Authority Level |
|---|---|---|---|---|
| MAP-UI-001 | 1.0 | 2026-10-14 | 0.9 | Informative |
Important
v1.0 (2026-10-14), review correction. v0.9’s own REWIRED capability rows for the redemption workflow (Student requests item redemption, Teacher approves redemption request, Teacher rejects redemption request, and the store-dashboard read row) were themselves stale, carrying this document’s superseded redemption_events/entitlement_consumptions terminology instead of the live PendingAction/EntitlementEvent model (DOM-STORE-001 §VI; app/feats/entitlement_lifecycle_feat.py). The rejection row was also substantively wrong: api.reject_redemption → execute_deny_redemption writes a terminal REVOKED EntitlementEvent and ends the entitlement, not “preserves” it as the row claimed — that preserving behavior belongs to the separate, not-yet-tabled api.return_redemption → execute_return_redemption action. Rewrote all four rows’ FEAT/Domain, Persistence, and Current State cells against the live code; no row’s REWIRED status changed.
v0.9 (2026-10-14), documentation modernization. Two self-contained defects, left over from earlier edits:
- §V’s Capability Rows table carried an earlier editing pass’s rows (status
VERIFY,grant_typeterminology) alongside a later pass’s rows for the same 11 capabilities (statusREWIRED,acquisition_typeterminology, matching the live code’sEntitlementEvent.acquisition_type). Removed the superseded earlier-pass rows and the now-zeroVERIFYline from the Summary; kept the later pass’s 15 rows (11 superseding the duplicates, 4 new insurance rows). Fixed one leftovergrant_typereference in the kept rows toacquisition_type. - Two different sections were both numbered “§VII” (Obligations Slice, Obligations Inventory). Renumbered them and everything after to VIII–XI.
No capability, FEAT, or wiring facts changed — only duplicate/stale rows and section numbers.
I. Purpose
This map connects audited template surfaces to their route, context, FEAT, domain, persistence, and read-model obligations.
It is the canonical planning artifact for turning template audit findings into executable rewiring work. GitHub issues and project boards may track execution, but this document preserves the architectural evidence.
This map is produced under SOP-DEV-002_CANONICAL_DOMAIN_RECONSTRUCTION_WORKFLOW.md.
II. Authority and Inputs
Authority order:
INV-CORE-000_CORE_INVARIANTS.mdINV-ARC-020_ACCESSIBILITY_REQUIREMENTS_AND_TEMPLATE_CONTRACT.mdDOM-PROD-001_PRODUCTIVITY_AND_PAYROLL_DOMAIN.mdFEAT-PROD-001_RECORD_ATTENDANCE_SESSION.mdFEAT-PROD-002_RECORD_HALL_PASS_LOG.mdFEAT-PROD-003_RECORD_PAYROLL_EVENT.mdDOM-OBL-001_OBLIGATIONS_DOMAIN.mdFEAT-OBLI-001_ASSESS_OBLIGATION.mdFEAT-OBL-002_ADVANCE_BILL_CYCLE.mdFEAT-OBL-003_SATISFY_OBLIGATION.mdDOM-STORE-001_STORE_AND_ENTITLEMENTS_DOMAIN.mdFEAT-STOR-001_STORE_PURCHASE.mdFEAT-STOR-002_ENTITLEMENT_LIFECYCLE_TRANSITION.mdFEAT-STOR-003_INSURANCE_CLAIM_LIFECYCLE.mdSOP-DEV-002_CANONICAL_DOMAIN_RECONSTRUCTION_WORKFLOW.mdMAP-UI-002_REQUEST_CONTEXT_AND_VIEW_MODEL_PIPELINE.md
Audit inputs (archived — historical evidence, not current authority):
These are the point-in-time audits this map was built from. They are preserved under
docs/archive/v2-tracking-2026/ and are cited here as provenance only. They do not carry authority,
and nothing in this map may be justified by them alone; the authority order above governs.
docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_ADMIN_E-P.md(archived)docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_STUDENT.md(archived)docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_ROUTE_AUDIT_ADMIN_AND_ANALYTICS.md(archived)docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_ROUTE_AUDIT_ADMIN_AND_SHARED.md(archived)docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_ROUTE_AUDIT_SYSADMIN_AND_SHARED.md(archived)
TEMPLATE_INTERFACE_AUDIT_2026-07-19.md was cited by earlier revisions of this map and no longer
exists anywhere in the repository. It is not recoverable and is listed here so the omission is not
mistaken for an oversight.
III. Row Contract
Each row describes one user-visible capability, not one variable or one template file.
| Field | Meaning |
|---|---|
| Capability | User-visible action, output, navigation, or client interaction |
| Surface | Template and route endpoint where the user sees or triggers the capability |
| Type | ACTION, OUTPUT, NAVIGATION, CLIENT_JS, or HOUSEKEEPING |
| Context | Required canonical context and temporal context |
| FEAT / Domain | Owning FEAT for mutation, plus owning domain for business truth |
| Persistence | Canonical table writes and reads |
| View Contract | Template variables or view-model shape that must be supplied |
| Current State | What the current branch appears to do |
| Rewire Status | READY, NEEDS_REWIRE, NEEDS_FEAT_DECISION, DELETE_OR_RESTORE, or VERIFY_ONLY |
Some rows carry a trailing audit-source column pointing into
docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/. Every such path is archived
provenance, per §II — it records which point-in-time audit observed the row, and is never a
statement of current behavior or authority.
IV. Productivity and Payroll Slice
Summary
| Status | Count | Meaning |
|---|---|---|
REWIRED |
7 | Template-triggered PROD action routes now call the canonical v2 interface or were intentionally collapsed |
REWIRED_READ |
6 | Template-rendered PROD read surfaces now use canonical v2 read contracts |
NEEDS_REWIRE |
0 | No unresolved PROD row remains in this map; template audits remain the final checklist |
Capability Rows
| Capability | Surface | Type | Context | FEAT / Domain | Persistence | View Contract | Current State | Rewire Status |
|---|---|---|---|---|---|---|---|---|
| Student views current productivity state and projected pay | student_dashboard.html; student.dashboard (GET /student/) |
OUTPUT |
Student CanonicalContext; class_id; seat_id; class-local day |
Read-only DOM-PROD; wage policy from Class Configuration; balance from Ledger |
Reads attendance_sessions, payroll settings, ledger balances, entitlement balance |
period_states, student_blocks, unpaid_seconds_per_block, projected_pay_per_block, unique_days_tapped, hall_pass_balance, display metadata |
Resolved 2026-07-21: template no longer dereferences student.display_first_name or student.hall_passes; route calls canonical attendance read service with CanonicalContext; display metadata supplies student name |
REWIRED_READ |
| Student views payroll history, attendance events, and projected pay | student_payroll.html; student.payroll (GET /student/payroll) |
OUTPUT |
Student CanonicalContext; class_id; seat_id; class-local payroll window |
Read-only DOM-PROD; FEAT-PROD-003 lineage for payroll events |
Reads attendance_sessions, payroll_event, payroll policy, ledger display data as secondary monetary facts |
student_blocks, unpaid_seconds_per_block, projected_pay_per_block, attendance_events, attendance_events_by_block, pay_rate_per_minute |
Resolved 2026-07-21: route groups canonical AttendanceSession rows by class section, uses PayrollEvent for last payroll, and calls canonical temporal resolver for elapsed-time display |
REWIRED_READ |
| Teacher views payroll dashboard and estimates | admin_payroll.html; admin.payroll (GET /admin/payroll) |
OUTPUT |
Teacher CanonicalContext; selected class_id; class-local payroll window |
Read-only DOM-PROD; Class Configuration for wage policy; Ledger for balances only |
Reads attendance_sessions, payroll_event, payroll settings, balances |
recent_payrolls, next_payroll_by_block, total_payroll_estimate, student_stats, payroll_history, all_students |
Resolved 2026-07-21 for GET read: recent activity, history tab, last-payroll stats, and total earned now derive from PayrollEvent rows with Ledger amount lookup by correlation_id; legacy payroll void controls removed from this template surface |
REWIRED_READ |
| Teacher runs attendance-based payroll | admin_payroll.html; admin.run_payroll (POST /admin/run_payroll) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; class-local payroll evaluation |
FEAT-PROD-003 with payroll_event_type = payroll; Ledger posting through FEAT-LED-000 / FEAT-LED-001 |
Writes payroll_event; writes Ledger monetary facts with shared correlation_id |
Redirect or JSON success; subsequent GET must show payroll event lineage and updated monetary facts | Resolved 2026-07-21: teacher clicking “Run Payroll” records payroll events, not manual_credit; route no longer uses FEAT-LED-004 or execute_admin_adjustments; it records one payroll event per student through record_payroll_event using a shared canonical run timestamp |
REWIRED |
| Teacher records manual payroll credit | admin_payroll.html; admin.payroll_manual_payment (POST /admin/payroll/manual-payment) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; target student seat |
FEAT-PROD-003 with payroll_event_type = manual_credit; Ledger through canonical monetary resolution |
Writes payroll_event; writes Ledger credit; no payroll amount stored on domain row |
Redirect back to payroll; display in payroll history/read model | Resolved 2026-07-21: any direct teacher-to-student money send is manual_credit; route calls record_payroll_event(... payroll_event_type="manual_credit"); template no longer exposes deduction or account-type controls because manual debits/fines belong to Obligations |
REWIRED |
| Teacher views payroll history | admin_payroll_history.html; admin.payroll_history (GET /admin/payroll-history) |
OUTPUT |
Teacher CanonicalContext; selected class_id; class-local timestamp display |
Read-only DOM-PROD payroll event lineage; Ledger amount display by correlation |
Reads payroll_event; joins Ledger facts by correlation_id for amount display only |
payroll_history entries with timestamp, class label, actor/target identity, amount, notes |
Resolved 2026-07-21: route reads PayrollEvent, derives class-local date filters through canonical_temporal_resolver, and template uses dict student_name directly |
REWIRED |
| Teacher views hall-pass queue and out-of-class state | admin_hall_pass.html; admin.hall_pass (GET /admin/hall-pass) |
OUTPUT |
Teacher CanonicalContext; selected class_id; class-local current day |
Read-only DOM-PROD; entitlement balance from Obligations/Entitlement |
Pending requests from pending_actions (authoritative_feat = FEAT-PROD-002, owner ruling 2026-10-01); issued passes from hall_pass_logs; out/returned state from attendance_sessions; entitlement state for balance |
pending_requests, issued_passes, out_of_class, verify_url, available_periods |
Resolved 2026-07-21: pending requests now come from ephemeral operational queue, not hall_pass_logs; issued/out state derives from canonical hall_pass_logs plus latest attendance_sessions |
REWIRED_READ |
| Teacher marks approved hall pass leave/return | admin_hall_pass.html; /api/hall-pass/<id>/leave, /api/hall-pass/<id>/return |
ACTION |
Teacher CanonicalContext; class_id; approving teacher seat; requested student seat; class-local request time |
FEAT-PROD-001 |
Writes append-only attendance_sessions rows for inactive/hall_pass and active/start_work; does not mutate hall_pass_logs lifecycle state |
Reloads hall-pass page; subsequent GET derives approved/out state from latest attendance event | Resolved 2026-07-21: endpoint no longer uses FEAT-ATTN-001 or legacy hall-pass mutation helpers for leave/return; it appends canonical attendance facts through record_attendance_session |
REWIRED |
| Teacher approves or rejects pending hall-pass request | Hall-pass request/approval controls routed through admin/API hall-pass endpoints | ACTION |
Teacher CanonicalContext; class_id; approving teacher seat; requested student seat; class-local request time; Class Configuration hall-pass settings |
FEAT-PROD-002; entitlement consumption in Obligations/Entitlement; hall-pass settings read from Class Configuration |
Pending request is a pending_actions row (DOM-STORE-001 §VII.B, owner ruling 2026-10-01); reject deletes it without writing PROD truth; approve deletes it in the same transaction that writes the pass; approve writes hall_pass_logs and entitlement consumption with shared correlation_id; attendance exit/return stays in attendance_sessions |
Pending request disappears; approved instruction appears in issued-pass read model | Resolved 2026-07-21: admin_hall_pass.html now approves/rejects pending requests; approve is the commit point into FEAT-PROD-002, reject performs no PROD write, and legacy HallPassLog.status mutation helpers were removed from the touched implementation path |
REWIRED |
| Student or teacher records productivity session state | Student dashboard attendance controls; student hall-pass controls; admin tap-in/tap-out routes | ACTION |
Live CanonicalContext; actor seat; target seat; class_id; CLE temporal evaluation |
FEAT-PROD-001 |
Writes append-only attendance_sessions; no current-state, elapsed-time, or payroll amount stored on row |
Dashboard button set is contextual: Start Work, Break, Leave, and Return; Student dashboard/payroll and admin attendance views update from append-only timeline |
Resolved 2026-07-21: student dashboard controls use v2 command surfaces (/api/tap for Start Work/Done for day, hall-pass checkout/checkin for Leave/Return); admin bulk tap-in/tap-out routes call record_attendance_session; legacy app.feats.attendance attendance writers, soft-delete helper, and seat_attendance_state status helper path were removed from the touched route surface |
REWIRED |
| Teacher views attendance log | admin_attendance_log.html; admin.attendance_log (GET /admin/attendance-log); /api/attendance/history |
OUTPUT |
Teacher CanonicalContext; selected class_id; class-local display |
Read-only DOM-PROD productivity timeline |
Reads attendance_sessions; derives display rows from target_seat_id, timestamp, status, reason_code |
blocks, class_labels_by_block; JS history payload with student_name, student_class_label, period, timestamp, status, reason |
Resolved 2026-07-21: history API now reads canonical append-only AttendanceSession fields and uses canonical_temporal_resolver for date filters; legacy tap-enable toggle removed from this template surface |
REWIRED_READ |
| Student reports attendance event issue | student_submit_issue.html; student.report_attendance_session_issue (GET, POST /student/help-support/attendance-session/<id>/report) |
ACTION |
Student CanonicalContext; class_id; seat_id; target attendance row belongs to same seat/class |
Support FEAT/domain owns issue filing; DOM-PROD owns referenced attendance fact |
Reads attendance_sessions; writes Support issue with related_record_type = attendance_session pointing at attendance fact |
Issue form with attendance_session; redirect to help/support on success |
Resolved 2026-07-22: route, endpoint, parameter, template url_for, and submitted related-record type use canonical attendance-session terminology; legacy tap_event URL/endpoint is not preserved |
REWIRED |
| Public hall-pass verification page | hall_pass_verify.html; public verify route |
OUTPUT |
Public capability token linked to teacher user_id; no live actor CanonicalContext; token resolves teacher-scoped verification authority across that teacher’s classes |
Read-only DOM-PROD; no mutation |
Reads teacher-scoped hall_pass_logs and current-day attendance facts without exposing unrelated teacher/class data; student query matches Seat.claim_first_name_hash + Seat.claim_last_name_hash |
Verification form/result page | Resolved 2026-07-21: class dropdown displays section + class display name while submitting class_id; route derives left/returned state from attendance_sessions; IdentityProfile is used only after unique match for display |
REWIRED_READ |
V. Store and Entitlements Slice
Summary
| Status | Count | Meaning |
|---|---|---|
NEEDS_REWIRE |
0 | No unresolved STORE row remains in this map; template audits remain the final checklist |
Capability Rows
| Capability | Surface | Type | Context | FEAT / Domain | Persistence | View Contract | Current State | Rewire Status |
|---|---|---|---|---|---|---|---|---|
| Teacher views store dashboard: items, pending redemptions, recent purchases, audit log | admin_store.html; admin.store_management (GET /admin/store) |
OUTPUT |
Teacher CanonicalContext; selected class_id |
Read-only DOM-STORE; Class Configuration for item catalog; Ledger for price display |
Reads store_items, store_item_visibility; pending and resolved redemption requests from PendingAction (redemption_query_service.list_pending_redemptions/list_resolved_redemptions); purchase history and entitlement balance from EntitlementEvent (redemption_events and entitlement_consumptions are superseded tables, not read — DOM-STORE-001 §VI) |
items, pending_redemptions, recent_purchases, collective_progress_by_item, audit_rows, rent_managed_item_ids, display metadata |
Route now assembles the canonical dashboard view model from PendingAction and EntitlementEvent rows; template consumes pending_redemptions, recent_purchases, and item purchase histories without stale StorePurchase assumptions |
REWIRED |
| Teacher creates store item | admin_store.html; admin.store_management (POST /admin/store) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat |
Store domain (DOM-STORE-001); store_items and store_item_visibility are catalog definitions owned by Store/Policies domain |
Writes store_items, store_item_visibility |
Redirect to store dashboard; subsequent GET shows new item | Route uses Store domain FEAT authority (FEAT-STOR-*) for catalog creation per decision 6 |
REWIRED |
| Teacher edits store item | admin_edit_item.html; admin.edit_store_item (GET, POST /admin/store/edit/<item_id>) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat |
Store domain (DOM-STORE-001); same as item creation | Writes store_items, store_item_visibility |
form, item, payroll_settings |
Route uses Store domain FEAT authority (FEAT-STOR-*) for catalog edit per decision 6 |
REWIRED |
| Teacher deactivates store item | admin_store.html; admin.delete_store_item (POST /admin/store/delete/<item_id>, /admin/item/deactivate/<item_id>) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat |
Store domain (DOM-STORE-001) for catalog mutation; monetary reversal, if needed for collective items, is a separate Ledger-bound workflow | Writes store_items (soft-delete) |
Redirect to store dashboard | Route uses Store domain FEAT authority (FEAT-STOR-*) for catalog deactivation per decision 6 |
REWIRED |
| Student browses store catalog and views owned items | student_shop.html; student.shop (GET /student/shop) |
OUTPUT |
Student CanonicalContext; class_id; seat_id |
Read-only DOM-STORE; Class Configuration for catalog; Ledger for balance display |
Reads store_items, store_products, store_item_visibility, rent_settings; entitlement balance from entitlement_events |
items, policy_uuid_by_item_id, entitlements, has_paid_rent, per_period_rent_item_ids, rent_free_uses, class_size, collective_progress |
Template now receives an exact policy_uuid_by_item_id map so the purchase modal can emit canonical policy_uuid instead of inferring from item_id; owned-items view now renders from entitlements |
REWIRED |
| Student purchases store item | student_shop.html (inline JS); api.purchase_item (POST /api/purchase-item) |
ACTION |
Student CanonicalContext; class_id; seat_id; passphrase verification; exact policy_uuid selected by the template |
FEAT-STOR-001 (acquisition_type = PURCHASE); Ledger posting through lawful Ledger FEAT |
Writes one EntitlementEvent grant row per purchased unit with shared correlation_id (quantity 5 = 5 entitlement rows, per FEAT-STOR-001); Ledger Transaction with shared correlation_id; selection reads store_products only to supply the exact UUID map |
JSON {status, message}; subsequent GET reflects purchase in owned-items list |
Route and template now use the exact-UUID purchase contract: the shop modal emits policy_uuid, and the FEAT resolves that immutable locator without item_id inference |
REWIRED |
| Student requests item redemption | student_shop.html (inline JS); api.use_item (POST /api/use-item) |
ACTION |
Student CanonicalContext; class_id; seat_id; passphrase verification; exact entitlement_id selected by the template |
FEAT-STOR-002: execute_use_item_immediate for instant-use items writes a terminal CONSUMED EntitlementEvent directly; execute_use_item_request for delayed items opens a PendingAction only, with no terminal event yet |
Instant-use items: writes a terminal CONSUMED EntitlementEvent. Delayed items: writes a PendingAction row (the request); no terminal event yet. redemption_events and entitlement_consumptions are superseded tables and are not written (DOM-STORE-001 §VI) |
JSON {status, message}; subsequent GET shows item status change |
Route now uses FEAT-STOR-002 and either consumes the entitlement immediately or opens the request as a PendingAction, through the canonical lifecycle primitives; the shop modal posts entitlement_id rather than legacy item_id |
REWIRED |
| Teacher approves redemption request | admin_store.html (inline JS); api.approve_redemption (POST /api/approve-redemption) |
ACTION |
Teacher CanonicalContext; class_id; actor teacher seat; target student seat |
FEAT-STOR-002 (execute_approve_redemption → consume_entitlement); approval writes the authoritative terminal CONSUMED EntitlementEvent |
Writes a terminal CONSUMED EntitlementEvent; deletes the resolved PendingAction (DOM-STORE-001 §VII.B). redemption_events and entitlement_consumptions are superseded tables and are not written (DOM-STORE-001 §VI) |
JSON {status, message}; subsequent GET removes item from pending list |
Route now uses FEAT-STOR-002 and consumes the entitlement through the canonical terminal lifecycle primitive, deleting the resolved PendingAction |
REWIRED |
| Teacher rejects redemption request | admin_store.html (inline JS); api.reject_redemption (POST /api/reject-redemption) |
ACTION |
Teacher CanonicalContext; class_id; actor teacher seat; target student seat |
FEAT-STOR-002 (execute_deny_redemption → revoke_entitlement); denial is final and terminates the entitlement — no refund, no void (route docstring) |
Writes a terminal REVOKED EntitlementEvent; deletes the resolved PendingAction. redemption_events and entitlement_consumptions are superseded tables and are not written (DOM-STORE-001 §VI) |
JSON {status, message}; subsequent GET removes item from pending list, consumed and not refunded |
Route now uses FEAT-STOR-002 and terminates the entitlement (REVOKED) on rejection, deleting the resolved PendingAction. Preserving the entitlement for a later request — this row’s earlier claim — is the separate api.return_redemption → execute_return_redemption action, not represented by its own row in this table yet |
REWIRED |
| Teacher adjusts hall-pass entitlements for a seat | student_detail.html; admin.adjust_hall_pass_entitlements (POST /admin/student/<seat_id>/adjust-hall-pass-entitlements) |
ACTION |
Teacher CanonicalContext; class_id; actor teacher seat; target student seat |
FEAT-STOR-004 for direct entitlement grant; FEAT-STOR-002 (revoke_entitlement for removals) |
Writes EntitlementEvent with append-only grant facts; balance derived from event history |
Redirect to student detail page | Route now uses the direct-grant FEAT for issuance and the terminal lifecycle FEAT for removals; no mutable counter; balance derivation is canonical | REWIRED |
| Teacher bulk adjusts hall-pass entitlements | admin_students.html (inline JS); admin.bulk_adjust_hall_pass_entitlements (POST /admin/students/bulk-adjust-hall-pass-entitlements) |
ACTION |
Teacher CanonicalContext; class_id; actor teacher seat; multiple target student seats |
FEAT-STOR-004 for direct entitlement grant; FEAT-STOR-002 (revoke_entitlement for removals) |
Writes EntitlementEvent per seat with append-only grant facts |
JSON {status, message, updated, errors} |
Route now uses the direct-grant FEAT for issuance and the terminal lifecycle FEAT for removals; same canonical append-only mechanism as single-seat adjust | REWIRED |
| Teacher processes insurance claim | admin_process_claim.html; admin.process_claim |
ACTION |
Teacher CanonicalContext; selected class_id; actor_role = teacher per FEAT-STOR-003 |
FEAT-STOR-003 for claim approval/rejection; transaction-insurance compensation through lawful Ledger FEAT; productivity-insurance compensation through DOM-PROD → payroll_event with payroll_type = MANUAL_CREDIT |
Templates exist on disk; routes consume canonical claim and policy records | Claim review surface is implemented against canonical claim retrieval and decision orchestration | Route bodies resolve claims, render policy review, and approve/reject through the canonical claim FEAT path | REWIRED |
| Student browses insurance marketplace and purchases initial coverage | student_insurance_marketplace.html; student.insurance_marketplace, student.purchase_insurance |
ACTION |
Student CanonicalContext; class_id; seat_id |
FEAT-STOR-001 for initial insurance acquisition (acquisition_type = PURCHASE with insurance capability); Obligations domain creates renewal assessment schedule upon purchase; obligation satisfaction causes OBLIGATION entitlement grant for ongoing coverage |
Templates render canonical insurance marketplace state | Initial purchase is wired through the marketplace and policy purchase routes; renewal remains an Obligations concern | Route now resolves class-scoped insurance policy versions, groups tiered offerings, and purchases through the entitlement-backed initial acquisition path | REWIRED |
| Student files insurance claim | student_file_claim.html; student.file_claim |
ACTION |
Student CanonicalContext; class_id; seat_id; actor_role = student per FEAT-STOR-003 |
FEAT-STOR-003 for claim submission (submit_insurance_claim() → status = SUBMITTED); claim does not consume the insurance entitlement |
insurance_claims |
policy, enrollment, claims_this_period, eligible_transactions, form, errors |
Route now resolves the active insurance entitlement from the purchased policy item and calls execute_claim_submission() on POST; claim rows are created against insurance_claims.entitlement_id, and submission does not consume the entitlement |
REWIRED |
| Student views insurance coverage and claim history | student_view_policy.html; student.view_policy |
OUTPUT |
Student CanonicalContext; class_id; seat_id |
Read-only DOM-STORE for entitlement and coverage state; read-only Obligations for renewal status |
insurance_claims, entitlements, obligation_assessments |
enrollment, policy, claims, now |
Route now resolves the active insurance entitlement from the policy item, derives claim history from insurance_claims.entitlement_id, and builds the coverage view from canonical entitlement + obligation rows |
REWIRED |
VI. Class Configuration Slice
Summary
| Status | Count | Meaning |
|---|---|---|
REWIRED |
7 | Verified against the code on 2026-09-17 |
OBSOLETE |
3 | Route or template deleted or renamed; the demand no longer applies as written |
NEEDS_REWIRE |
1 | admin.dashboard’s class list still queries ClassEconomy/Seat inline |
VERIFY_ONLY |
2 | Verification pending |
Re-verified row by row on 2026-09-17. The previous counts (NEEDS_REWIRE 15+,
VERIFY_ONLY 8+) were wrong in both directions: they predated the FEAT-CLASS
wiring and several route deletions, and they exceeded the number of rows this
section holds.
Capability Rows
| Capability | Surface | Type | Context | FEAT / Domain | Persistence | View Contract | Current State | Rewire Status |
|---|---|---|---|---|---|---|---|---|
| Teacher creates and names a new class | admin_dashboard.html; admin.create_class (POST /admin/create-class) |
ACTION |
Teacher CanonicalContext; actor teacher seat; timezone selection |
FEAT-CLASS-001 (create boundary); teacher seat becomes class owner |
Writes ClassEconomy row with canonical class_id, join_code, section, timezone; writes initial EconomicEngine version |
class_id, join_code, class_name, timezone, initial economy_policy_mode |
Wraps creation in FEAT-CLASS-001 with a payload-derived idempotency key, calling classroom_setup.create_class. Surface is admin_create_class.html / admin.create_new_class |
REWIRED |
| Teacher views class list and summaries | admin_dashboard.html; admin.dashboard (GET /admin/) |
OUTPUT |
Teacher CanonicalContext; actor teacher seat |
Read-only DOM-CLASS; Class Configuration for per-class economy and feature state |
Reads ClassEconomy, class_features, EconomicEngine |
all_classes, current_class_context, class_stats (student count, feature status, economic state) |
STILL OPEN: _get_validated_teacher_class_options queries ClassEconomy/Seat inline; get_all_classes_by_teacher() is imported but never called. The class switcher is fed by the layout context processor, so this row’s all_classes/class_stats contract is itself partly obsolete |
NEEDS_REWIRE |
| Teacher selects current class context | admin_dashboard.html; admin.set_current_class (POST /admin/current-class) |
ACTION |
Teacher CanonicalContext; actor teacher seat; target class_id |
Session management only; no FEAT mutation required | No persistence write; session state only | Redirect to dashboard with new class context active | Route correctly uses session state only; no domain mutation | VERIFY_ONLY |
| Teacher enables feature for class | admin_feature_settings.html; admin.feature_settings (GET/POST /admin/feature-settings) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; class-local time |
FEAT-CLASS-004 (enable feature) |
Writes class_features row with economic_version_id link to current engine |
Feature activation status; error on duplicate activation | Mutation moved to POST /admin/feature-settings/update, which calls execute_enable_feature(); the GET surface is a view model (build_feature_settings_page_view) |
REWIRED |
| Teacher disables feature for class | admin_feature_settings.html; admin.feature_settings (GET/POST /admin/feature-settings) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; class-local time |
FEAT-CLASS-004 (disable feature) |
Writes class_features row with economic_version_id = NULL (soft disable per INV-ARC-016) |
Feature deactivation status; error if feature not currently enabled | Same route calls execute_disable_feature(). Disablement is recorded with a deleted_at row, not economic_version_id = NULL; essential features are refused |
REWIRED |
| Teacher transitions economic policy mode | admin_economy_health.html; admin.apply_economy_rebalance (POST /admin/economy-policy/rebalance) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; class-local time; target policy mode selection |
FEAT-CLASS-005 (economic engine evolution) |
Writes new EconomicEngine version with economy_policy_mode; links all affected features to new version via class_features rows; preserves version chain via previous_version_id |
Rebalance confirmation; updated class economy state | Capability is admin.update_economy_policy, calling execute_evolve_economic_engine() with the enabled feature list; the rebalance route opens one FEAT-CLASS-005 context. admin_economy_health.html is deleted — surface is admin_economic_engine.html |
REWIRED |
| Teacher updates class timezone | admin_settings.html; admin.set_class_timezone (POST /classes/<class_id>/timezone) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; IANA timezone selection |
FEAT-CLASS-001 (class boundary mutation) or dedicated FEAT-CLASS-002 TBD |
Writes ClassEconomy.timezone column; affects all class-local temporal evaluation |
Timezone update confirmation; class context reflects new timezone | OBSOLETE: route and template deleted. classes.class_timezone is NOT NULL and immutable, set once at creation, so no FEAT applies |
OBSOLETE |
| Teacher views class configuration and settings | admin_settings.html; admin.settings (GET /admin/settings) |
OUTPUT |
Teacher CanonicalContext; selected class_id; actor teacher seat |
Read-only DOM-CLASS; all class configuration from canonical ClassEconomy and feature state |
Reads ClassEconomy, class_features, EconomicEngine, related payroll/rent/banking settings owned by other domains |
class_config, feature_status, economy_mode, policy_settings (delegated to domain-specific read services) |
OBSOLETE as written: renamed to admin.customizations / admin_customizations.html. The successor still reads raw ORM and mutates display_name/section inline under a FEAT-IDEN-001 context; feature and policy display split onto admin.feature_settings and admin.economic_engine |
OBSOLETE |
| Teacher views feature configuration status | Feature settings page; read paths | OUTPUT |
Teacher CanonicalContext; selected class_id |
Read-only DOM-CLASS for feature enrollment; delegated domain reads for feature-specific settings (payroll, rent, banking, hall-pass) |
Reads class_features for enrollment state; delegated reads to domain-specific settings tables |
enabled_features, feature_settings_by_feature (delegated to domain services) |
Routes currently use direct queries; must call class_configuration_query_service.get_class_features() and delegate to domain-specific services |
VERIFY_ONLY |
| Teacher views class economy dashboard | admin_economy_health.html; admin.economy_health (GET /admin/economy-health) |
OUTPUT |
Teacher CanonicalContext; selected class_id; class-local temporal context |
Read-only DOM-CLASS for economy mode and rebalance state; cross-domain reads for health analysis |
Reads ClassEconomy, EconomicEngine, class_features; delegated reads from Payroll, Obligations, Store domains |
economy_state, policy_mode, rebalance_status, health_summary (delegated to domain-specific read services for feature details) |
OBSOLETE as written: route and template deleted. Successor admin.economic_engine uses get_class_economy() but still assembles its health view inline in the route |
OBSOLETE |
| Teacher views class enrollment and student list | admin_students.html; admin.students (GET /admin/students) |
OUTPUT |
Teacher CanonicalContext; selected class_id; actor teacher seat |
Read-only DOM-IDEN for seat/student roster; DOM-CLASS for class scope |
Reads seats scoped by class_id; cross-domain reads for student-level data |
students (roster with identity/seat data); class_context |
Route resolves scope and delegates to build_class_roster_view() (app/services/roster_view_model.py); the template consumes pre-built rows |
REWIRED |
| Teacher deletes a class / join code | admin_dashboard.html; admin.delete_join_code (POST /admin/join-code/delete) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; dangerous operation |
FEAT-CLASS-006 boundary destruction |
Soft-delete or hard-delete ClassEconomy row; cascading delete of dependent feature and engine rows |
Confirmation and redirect; class removed from teacher’s class list | Target resolves from canonical context only, authority-checked with verify_teacher_owns_class; destruction runs through FEAT-CLASS-006, escalating to FEAT-IDEN-007 for the last class; FEAT-CLASS-006 re-evaluates that escalation under lock and refuses rather than orphaning the principal. Surface is admin_class_delete.html |
REWIRED |
VII. Obligations Slice
Summary
| Status | Count | Meaning |
|---|---|---|
NEEDS_REWIRE |
0 | No unresolved OBL row remains in this map; template audits remain the final checklist |
Capability Rows
| Capability | Surface | Type | Context | FEAT / Domain | Persistence | View Contract | Current State | Rewire Status |
|---|---|---|---|---|---|---|---|---|
| Student views rent obligations and payment status | student_rent.html; student.rent (GET /student/rent) |
OUTPUT |
Student CanonicalContext; class_id; seat_id; class-local temporal context |
Read-only DOM-OBL; rent source terms from Class Configuration; payment truth from Ledger |
Reads assessment_events (including PAYMENT and WAIVED event rows), bill_cycles, ledger_transaction |
rent_items, active_waivers, current_period_start, current_period_end, current_coverage_due_date, rent_status_counts, rent_status_total, unpaid_rent_log |
Route delegates to build_student_obligation_view(obligation_type='RENT'), reading obligation assessments and bill cycles; the legacy block/period variables are gone |
REWIRED |
| Teacher manages rent configuration and waiver controls | admin_rent_settings.html; admin.rent_settings (GET|POST /admin/rent-settings) |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat; class-local temporal context |
FEAT-OBL-002 for bill-cycle progression inputs and FEAT-OBL-003 for rent waiver actions; Class Configuration for rent policy definition |
Reads rent_settings; reads and writes assessment_events (including PAYMENT/WAIVED rows), bill_cycles; ledger only for payment-backed satisfaction |
settings, rent_items, all_students, active_waivers, current_period_start, current_period_end, current_coverage_due_date, rent_status_counts, rent_status_total, unpaid_rent_log |
STILL OPEN (FEAT half done): writes run through one FEAT-SETTINGS-001 context and waivers through FEAT-OBL-003. Policy and cycle display are still assembled inline — the period maths imports three private helpers from the student blueprint — and no surface drives FEAT-OBL-002 |
NEEDS_REWIRE |
| Student files insurance claim against active coverage | student_file_claim.html; student.file_claim (GET|POST /student/insurance/claim/<int:policy_id>) |
ACTION |
Student CanonicalContext; class_id; seat_id |
FEAT-STOR-003; renewal/source coordination may consult DOM-OBL for premium settlement lineage |
Reads insurance_claims, entitlements, and obligation renewal lineage only |
policy, enrollment, claims_this_period, eligible_transactions, form, errors |
Already audited as an insurance claim surface; claim submission must remain separated from obligation event creation even when the underlying premium lifecycle is obligations-backed | REWIRED |
| Student views insurance coverage and policy status | student_view_policy.html; student.view_policy (GET /student/insurance/policy/<...>) |
OUTPUT |
Student CanonicalContext; class_id; seat_id |
Read-only DOM-STORE for entitlement lifecycle; read-only DOM-OBL for renewal/premium status |
Reads entitlements, insurance_claims, and obligation renewal lineage |
enrollment, policy, claims, now |
The insurance view model remains entitlement-led, but its renewal/read status must reflect obligations-owned bill-cycle and assessment facts | REWIRED_READ |
| Teacher reviews insurance claim lifecycle | admin_process_claim.html; admin.process_claim |
ACTION |
Teacher CanonicalContext; selected class_id; actor teacher seat |
FEAT-STOR-003; compensation path may coordinate Ledger or Payroll, but never obligation event mutation directly |
Reads insurance_claims, entitlements, and claim lineage; writes claim decision only |
claim, policy, enrollment, claims, decision_form |
Existing claim workflow remains the consumer of obligation-backed coverage history rather than an obligation writer | REWIRED |
VIII. Obligations Inventory
This inventory is the full obligations-facing template set surfaced by the audit docs in docs/TRACKING/. It includes both live routes and currently aborted surfaces so the rewiring plan can close the entire branch of work without rediscovering endpoints later.
| Template | Route | Current Status | Route Variables / View Contract | Obligations Role | Audit Source |
|---|---|---|---|---|---|
student_rent.html |
student.rent (GET /student/rent) |
Live, legacy view model | student, settings, student_blocks, period_status, current_block, checking_balance, savings_balance, payment_due_date, grace_end_date, grace_end_date_for_status, payment_history, rent_items, days_until_due; Jinja reads feature_settings.rent_enabled, current_class_context.teacher_name, current_class_context.block_display, current_block|upper, settings.rent_amount, settings.due_day_of_month, payment_history, csrf_token() |
Rent obligation read surface; must derive assessments, satisfactions, bill cycles, due state, and waivers from DOM-OBL |
docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_STUDENT.md (archived) |
admin_rent_settings.html |
admin.rent_settings (GET|POST /admin/rent-settings) |
Live, legacy view model | settings, total_students, active_waivers, all_students, payroll_warning, payroll_settings, settings_block, teacher_blocks, class_labels_by_block, join_codes_by_block, rent_items, rent_active_for_period, period_label, rent_status_counts, rent_status_total, payment_log, unpaid_rent_log, current_period_start, current_period_end, next_due_date, student_past_due_json, current_coverage_due_date, upcoming_coverage_due_date, selected_feature_scope; Jinja reads settings.is_enabled, settings.rent_amount, settings.frequency_type, settings.late_penalty_amount, settings.late_penalty_type, settings.late_penalty_frequency_days, payment_log, unpaid_rent_log, format_utc_iso(waiver.waiver_start_date/end_date), student_past_due_json, selected_feature_scope.block, rent_items|length |
Rent configuration and waiver controls; must orchestrate FEAT-OBL-002 / FEAT-OBL-003 and surface canonical bill-cycle and satisfaction facts |
docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_ROUTE_AUDIT_ADMIN_AND_SHARED.md (archived) |
student_insurance_marketplace.html |
student.student_insurance (GET /student/insurance) |
Live route in current checkout | my_policies, available_policies, tier_groups, my_claims, can_purchase, enrolled_tiers, repurchase_blocks, now; Jinja reads feature_settings.rent_enabled and feature_settings.insurance_enabled, current_class_context.teacher_name, current_class_context.block_display, my_policies|length, my_claims|length, enrollment.policy.description, enrollment.policy.premium, enrollment.coverage_start_date > now, url_for('student.file_claim'), url_for('student.view_policy'), url_for('student.cancel_insurance'), csrf_token(), policy.description, url_for('student.purchase_insurance') |
Insurance purchase entry point; renewal timing must remain obligations-backed without making the marketplace an obligation writer | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_STUDENT.md (archived) |
student_file_claim.html |
student.file_claim (GET|POST /student/insurance/claim/<int:policy_id>) |
Live route in current checkout | form, policy, enrollment, contract_title, contract_description, claim_type, contract_claim_time_limit_days, contract_max_claim_amount, contract_max_claims_count, contract_max_claims_period, eligible_transactions, claims_this_period, remaining_period_cap, errors, now; Jinja reads contract_title, url_for('student.file_claim'), form.hidden_tag(), claim_type == 'transaction_monetary', form.transaction_id, form.description, url_for('student.student_insurance'), contract_description | markdown, enrollment.coverage_start_date.strftime(...) |
Claim submission surface; must remain separated from obligation creation/satisfaction | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_STUDENT.md (archived) |
student_view_policy.html |
student.view_policy (GET /student/insurance/policy/<int:enrollment_id>) |
Live route in current checkout | student, enrollment, claims, now; Jinja reads enrollment.contract_title, enrollment.contract_description, enrollment.policy.premium, enrollment.policy.autopay, enrollment.purchase_date, enrollment.contract_max_claim_amount, enrollment.next_payment_due, claim.incident_date, waiting-period logic, url_for('student.file_claim'), url_for('student.cancel_insurance'), csrf_token() |
Insurance coverage and claim history read surface; should reflect obligations-owned renewal lineage | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_STUDENT.md (archived) |
admin_insurance.html |
admin.insurance_management (GET|POST /admin/insurance) |
Live route in current checkout | policies (insurance_policies rows), claims, selected_scope |
Teacher insurance catalog and policy management surface; downstream obligations truth must not be mutated directly | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_ADMIN_E-P.md (archived) |
admin_edit_insurance_policy.html |
admin.edit_insurance_policy (GET|POST /admin/insurance/edit/<int:policy_id>) |
Live route in current checkout | policy, policy_version, payload, available_versions, store_items, current_page |
Insurance policy edit surface; class-config authority only, but it is part of the obligations/insurance rewiring boundary because renewal reads depend on it | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_ADMIN_E-P.md (archived) |
admin_process_claim.html |
admin.process_claim (GET|POST /admin/insurance/claim/<claim_id>) |
Live route in current checkout | claim, claim_type, contract_title, contract_description, contract_waiting_period_days, contract_claim_window_days, contract_reimbursement_percentage, contract_period_allowance, contract_period_consumed, contract_max_payout_per_period, remaining_period_cap, coverage_start, coverage_effective_date, claims_stats, policy, form |
Teacher claim decision surface; every contract term projected by describe_claim_contract so the display cannot diverge from the submission gates |
docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_ADMIN_E-P.md (archived) |
admin_view_student_policy.html |
None — admin.view_student_policy was removed |
Orphaned template; the handler carried @admin_required but no route decorator, so it never rendered |
— | Teacher insurance policy review surface, unimplemented. Any revival must project real policy terms, not placeholders | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_ROUTE_AUDIT_ADMIN_AND_SHARED.md (archived) |
admin_dashboard.html |
admin.dashboard (GET /admin/) |
Live summary surface | system_announcements, show_recovery_setup, total_students, total_balance, avg_balance, total_pending_actions, pending_redemptions_count, pending_hall_passes_count, pending_insurance_claims_count, total_transactions_today, total_payroll_estimate, payroll_updated_at, next_payroll_date, recent_redemptions, recent_hall_passes, recent_insurance_claims, recent_transactions, recent_logs, seat_profiles, show_insurance_tier_prompt, current_page; Jinja reads pending insurance counts and claim rows |
Pending insurance claims count is a cross-domain summary that should remain read-only and trace back to claim lineage, not mutate obligations | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_ROUTE_AUDIT_ADMIN_AND_ANALYTICS.md (archived) |
admin_economy_health.html |
admin.economy_health (GET /admin/economy-health) |
Live summary surface | current_page, blocks, selected_block, payroll_settings, has_payroll_settings, cwi_calc, expected_hours, pay_rate_per_minute, rent_settings, insurance_count, store_item_count, fine_count, banking_settings, banking_summary, analysis, warnings_by_level, warnings_by_feature, actionable_warning_count, health_warning_summary, recommendations, snapshot, analysis_schedule, policy_modes, policy_summary, pending_rebalance_effective_at, rebalance_preview, show_rebalance_review, feature_links, payroll_link, banking_link, rent_link, insurance_link, store_link; Jinja reads rent and insurance recommendations and policy summary fields |
Shows rent and insurance policy summaries; it is not an obligations writer, but it must not invent debt state outside canonical reads | docs/archive/v2-tracking-2026/TEMPLATE_AUDIT_FOR_REWIRING/TEMPLATE_AUDIT_ADMIN_E-P.md (archived) |
Notes:
student_account_claim.htmlis not obligations-owned; it is identity recovery / onboarding and remains outside this inventory.admin_help_support.htmlis orphaned and not part of the obligations rewrite surface.- Insurance template rows are included because their current read/write paths depend on obligations-backed renewal and satisfaction even though claim ownership remains in Store and Entitlements.
IX. Issue and Project Shape
GitHub issues should be generated from this map by capability group, not by template variable.
Recommended issue groups for the Productivity and Payroll slice:
- Student productivity read model: dashboard plus
student_payroll.html - Admin payroll read model: payroll dashboard plus history
- Payroll command path: run payroll and manual credit through
FEAT-PROD-003 - Hall-pass read and command path: queue, approval, verification
- Attendance session command path: student/API/admin tap routes through
FEAT-PROD-001 - Attendance support issue terminology: resolved to canonical attendance-session route and related-record reference
Recommended issue groups for the Obligations slice:
- Student rent read model:
student_rent.htmlGET — canonical assessments, satisfactions, bill cycles, and overdue projection - Admin rent configuration and waiver control:
admin.rent_settingsGET|POST — policy, cycle progression, assessment, and satisfaction split - Insurance marketplace read model:
student.student_insuranceGET — canonical entitlement plus obligations-backed renewal status - Insurance claim submission:
student.file_claimGET|POST — preserve claim workflow separation from obligation mutation - Insurance policy detail read:
student.view_policyGET — claim history plus obligations-backed renewal status - Insurance catalog edit:
admin.insurance_managementandadmin.edit_insurance_policy— class-config authority with obligations-aware downstream reads - Insurance claim decision:
admin.process_claim— claim review surface over obligations-backed coverage state - Summary surfaces:
admin.dashboardandadmin.economy_health— obligations counts and policy summaries as read-only projections
Recommended issue groups for the Store and Entitlements slice:
- Item catalog CRUD: rewire
admin.store_managementPOST,admin.edit_store_item,admin.delete_store_itemto Class Configuration domain FEAT; fix current wrong FEAT labels - Store dashboard read model:
admin_store.htmlGET — remove stale purchase-history field assumptions, remove GET-path FEAT wrapper, align view contract to MAP-UI-002 pipeline - Store dashboard read model:
admin_store.htmlGET — remove stale purchase-history field assumptions, remove GET-path FEAT wrapper, align view contract to MAP-UI-002 pipeline - Student store read model:
student_shop.htmlGET — present exactpolicy_uuid_by_item_idin the template contract and render owned items throughentitlements - Purchase command path:
api.purchase_itemthroughFEAT-STOR-001— exact-UUID purchase flow fromstudent_shop.html, create per-unit entitlement grant rows, eliminateuses_remaining/bundle_remainingmutable counters, verify idempotency replay - Redemption command path:
api.use_item,api.approve_redemption,api.reject_redemptionthroughFEAT-STOR-002—student_shop.htmlpostsentitlement_id, writeentitlement_consumptionsterminal events on approval only, fix rejection to preserve entitlement (no refund, no terminal event), resolve Ledger domain boundary - Entitlement adjust command path:
adjust_hall_pass_entitlementsandbulk_adjust_hall_pass_entitlements— fix FEAT labels toFEAT-STOR-001/FEAT-STOR-002 - Insurance acquisition: restore
student.insurance_marketplaceandstudent.purchase_insuranceagainstFEAT-STOR-001for initial purchase; wire Obligations for renewal assessment/satisfaction →OBLIGATIONentitlement grant - Insurance claims: restore
student.file_claimagainstFEAT-STOR-003for submission; restoreadmin.process_claimfor teacher approval/rejection with type-specific compensation (Ledger for transaction-insurance,DOM-PRODfor productivity-insurance) - Insurance catalog and policy read: restore
admin.insurance_managementandadmin.edit_insurance_policyfor Class Configuration catalog definition and Obligations renewal schedule; restorestudent.view_policyfor entitlement/coverage read model
Each issue should include:
- map row(s)
- audited template(s)
- route endpoint(s)
- required context
- FEAT/domain authority
- canonical writes
- read/view-model contract
- targeted validation command
X. Resolved Decisions
Productivity and Payroll
- Student dashboard attendance controls must not be a generic tap-in/tap-out pair. The canonical contextual button set is
Start Work,Break,Leave, andReturn, derived from current productivity and hall-pass state. - Public hall-pass verification remains outside live actor
CanonicalContext. It uses a public capability token linked to the teacher’suser_id; resolving that token grants read-only teacher-scoped hall-pass verification authority because a teacher may have one physical hall-pass verification surface shared among classes. - Direct teacher-to-student money send is
manual_creditunderFEAT-PROD-003. Teacher clickingRun Payrollispayroll, even if manually triggered by the teacher. - Entitlement terminal truth lives in
entitlement_consumptions, not in legacy purchase state or transient redemption rows.redemption_eventsis an append-only audit log of the redemption workflow (REQUEST,APPROVED,REJECTED);entitlement_consumptionsholds the authoritative terminal events (CONSUMED,EXPIRED,REVOKED). Any denormalized read cache must be derived from the canonical entitlement events. - Rejected redemption does not terminate the entitlement. A teacher rejecting a redemption request means “I will not fulfill this now” — the student retains the entitlement and may request redemption again. Only approval writes a
CONSUMEDterminal event toentitlement_consumptions. The current code’s behavior of issuing a Ledger refund on rejection is wrong on both counts. - FEAT-STOR-001 atomicity applies to entitlement grants, not purchase-history rows. A quantity-5 purchase creates five distinct entitlement grant rows with a shared
correlation_id. The current code must create per-unit entitlement grants. - Legacy mutable counters like
uses_remainingandbundle_remainingare prohibited by DOM-STORE-001. Remaining uses must be derived from entitlement grant count minusentitlement_consumptionsterminal event count. These columns must be removed or deprecated. - Legacy redemption action enums must use uppercase values (
REQUEST,APPROVED,REJECTED) matching DOM-STORE-001, not lowercase. - Store FEATs must not create
Transactionrecords directly. Ledger writes must go through lawful Ledger FEAT with a sharedcorrelation_id. ✅ RESOLVED (2026-08-03): Redemption disposition FEAT was deleted during store domain rebuild. Insurance claim lifecycle (FEAT-STOR-003) and entitlement transitions (FEAT-STOR-002) now correctly coordinate with Ledger domain through FEAT-LED-001 for all financial writes. - Hall-pass entitlement grants by teacher are
MANUAL_GRANTunderFEAT-STOR-001; removals arerevoke_entitlement()underFEAT-STOR-002. - Store item catalog CRUD (create, edit, deactivate) is Class Configuration, not a Store FEAT.
store_itemsandstore_item_visibilityare catalog definition tables. The current code’sFEATContext("FEAT-STOR-001")andFEATContext("FEAT-STOR-003")labels on these routes are wrong. - Insurance initial acquisition is a Store purchase through
FEAT-STOR-001. Renewal assessment and satisfaction belong to the Obligations domain. When an obligation is satisfied (e.g., recurring premium paid), Obligations creates anOBLIGATIONentitlement grant — Store does not own the renewal cycle. Insurance capabilities are surviving surfaces that must be rewired, not deleted. - Insurance claim lifecycle is governed by
FEAT-STOR-003. Claim activity does not consume the insurance entitlement. Transaction-insurance compensation goes through lawful Ledger FEAT; productivity-insurance compensation goes throughDOM-PRODas apayroll_eventwithpayroll_type = MANUAL_CREDIT. Store must not directly create payroll events or Ledger transactions for insurance compensation.
Store and Entitlements Decision Authority
See decisions 4-13 above.
Class Configuration
- Class creation writes both
ClassEconomyrow and initialEconomicEngineversion in a single FEAT transaction (FEAT-CLASS-001). Teacher seat becomes class owner through teacher_user_id linkage. - Feature enablement appends new
class_featuresrow witheconomic_version_idlinked to currentEconomicEngineversion (FEAT-CLASS-004). Features are enabled only if valid and not already enabled. - Feature disablement appends new
class_featuresrow witheconomic_version_id = NULL, implementing soft disable per INV-ARC-016. Disablement does not require economic engine change. - Economic policy transitions create new immutable
EconomicEngineversion withprevious_version_idlinking to predecessor; affected features are re-linked to new version via newclass_featuresrows (FEAT-CLASS-005). Policy mode changes are versioned history, not mutable state. - Timezone selection is class-scoped and affects all class-local temporal evaluation through canonical_temporal_resolver at CLE (class-local evaluation) scope. Timezone is immutable after class creation or requires engine evolution decision.
- Store item catalog CRUD (
create,edit,deactivate) belongs to Store domain, not Class Configuration, per DOM-STORE-001. These routes should call Store/Entitlements FEATs, not CLASS FEATs. (See MAP-UI-001 Store Slice for store_management, edit_store_item, delete_store_item routes.) - Class deletion or join_code removal is a dangerous operation requiring admin confirmation. Implementation details (hard delete vs. soft delete, cascade semantics) are governed by DOM-CLASS-002 retention policy and INV-ARC-016 append-only constraints.
XI. Amendment
Revisions to this map must update the version, preserve the row contract, and cite any newly audited template-route source documents used to add rows.
Last updated: 2026-10-14