Lewati ke isi

T6B SC-FEES / W10 Product Decision Gate

Issued: 2026-08-17
Historical status at issue: FAIL — ENTRY BLOCKED Historical engineering label: T6B ENTRY BLOCKED — NAMED PRODUCT DECISIONS REQUIRED

Current status (2026-08-17): APPROVED FOR ENGINEERING — see immutable contract Current engineering label: T6B ENGINEERING AUTHORIZED — IMPLEMENTATION NOT YET CERTIFIED

No signed immutable W10 / SC-FEES product contract exists. Catalog, test matrix, and STAB-014 still mark W10 BLOCKED. Current Fees code is not an approved lifecycle. Implementing inferred behavior would invent posting, refund, maker-checker, gateway, or journal semantics.

Phases 4–10 (canonical state machine, payment integrity, FE surface, PKG-FEES-W10 runtime, UAT) were not entered.

T6A independent certification of W03 / SC-ADM is out of scope and is not reused as Fees evidence.

Gate result

# Property Signed immutable approval? Current evidence Required decision (not implemented)
1 Fee product/rule/template ownership NO scola.fee.template lives in scola_fees. Catalog proposes Finance/Billing PO + Treasurer SME. financeApp.js labels the shell package: "SC-FIN" while SPP leaves are intended SC-FEES. Named owner of product, rule, and template; SC-FEES vs SC-FIN boundary.
2 Effective date and rule change NO DEC-008 unsigned for Fees. Templates/schedules have no signed effective-dated supersession. Catalog: pricing/effective-date require DEC-008. Who may change an active rule; from-when; whether billed enrollments freeze the old amount.
3 Student enrollment that may be billed NO scola.student.fee.enrollment unique (student_id, template_id). Lookups in fee_enrollment_api.py sudo-search op.student without company filter. STAB-014 open. Which W02 enrollment/status is billable; company-scoped student predicate.
4 Tenant/company scope of student, course, batch, fee, invoice, payment NO STAB-014: enrollment save/delete browse caller IDs then write. Mixed FK atomic denial is unsigned and unproven. RT-W10-TEN-01 BLOCKED. Every FK must belong to active company; mixed FKs fail atomically.
5 Maker-checker for create, approve, post, verify, reject, refund, reversal NO Enrollment has draft/pending_approval/approved/rejected/cancelled. Manual payment action_verify writes state without SoD. Accounting approve writes admin_state. DEC-004 unsigned for Fees. Named actor × action; self-approval denied or allowed.
6 Who may see student balance NO Capabilities finance.billing.view / finance.fees.view are assigned to several roles including leadership. Prefix /api/v1/finance/ maps to view. Named viewer set; field projection of amounts.
7 Parent sees only linked children NO parent_billing_api.py exists. Parent/portal fees bridges are auto_install but uninstalled on current mixed dev/demo DBs. RT-W10-SCP-01 BLOCKED. Active parent-child predicate; guessed invoice ID fail-closed.
8 Student self-scope NO Student portal billing is optional leaf. No signed self-scope contract. Student may read/pay only own bills.
9 Cashier / treasurer scope NO Caps: finance.billing.receive_cash, finance.billing.verify, finance.payment.manage. Role binding vs capability split is unsigned. Catalog: cashier/treasurer proposed. Cashier cannot change fee rules; treasurer cannot self-verify if SoD applies.
10 School admin post vs configure NO school_admin proposed in product contract. Whether they may post/verify/refund is unsigned. Config-only vs collect/post authority.
11 Payment channels in V1 NO Manual transfer/cash APIs plus Midtrans/Xendit public callbacks (payment_gateway_api.py). Catalog: cash/transfer/gateway are channels in one lifecycle. Exact V1 channel list.
12 Manual cash / transfer NO manual_payment_api.py create/proof/submit/verify/reject/cash. States pending/verified/rejected only. Evidence rules; who records cash; when balance updates.
13 Payment gateway NO Public /payment/callback/midtrans and /payment/callback/xendit. Timeout/retry/signature policy unsigned. RT-W10-IDM-01 BLOCKED. Provider list; signature; replay; timeout.
14 Payment proof attachment type/size/retention NO Proof upload exists. No signed DPO type/size/scan/retention. Type/size/signature/scan; who may download; retention/delete.
15 Duplicate submission / idempotency NO No durable application idempotency key on bill/payment/receipt. Enrollment unique is student+template only. RT-W10-IDM-01 BLOCKED. Keys + unique DB constraints for bill, payment, callback, receipt, refund.
16 Gateway timeout and retry NO No signed timeout/retry/dead-letter state. RT-W10-REC-01 BLOCKED. Timeout state; retry; recovery queue.
17 Overpayment NO Catalog lists overpayment as needing owned compensating workflow. Credit, reject, or apply-to-next; who authorizes.
18 Partial payment NO Schedule states draft/generated/invoiced/paid/cancelled; Odoo payment_state related. Partial is unsigned. Allowed or not; how remaining balance is computed on server.
19 Refund / reversal NO No Fees refund/reversal state machine. Dashboard reads Odoo out_refund. RT-W10-STA-01 BLOCKED. STAB-014 / BLK-A14. Who may request/approve; predecessor states; journal owner.
20 Failed payment recovery NO Catalog: rejected proof remains non-posted; recovery unsigned. Authoritative pending/reconcile/retry path.
21 Receipt generation NO Manifest comments # 'report/receipt_template.xml' # TODO: Fix Odoo 17 compatibility. When a receipt exists; idempotency; who may download.
22 Journal / accounting boundary NO scola_fees depends on Odoo account. payment_accounting_api.py uses account.payment.register.sudo(). Product contract: do not expose accounting/BOS as SC-FEES. Whether a Fees payment creates a journal; which journal; company scope.
23 Posting in SC-FEES vs SC-FIN NO RT-W10-XMD-01 BLOCKED — journal/bridge ownership. T6G owns SC-FIN. Implementing posting now would certify an uncertified accounting path. Posting stays out of V1 SC-FEES or explicit tested bridge after both SKUs.
24 Scholarship / discount / installment ownership NO Models scola.scholarship.type, scola.installment.preset in scola_fees. Catalog: optional scholarship/installment require DEC-008. Owner; negative-balance prohibition; Fees vs Admissions scholarship.
25 Bridge Admissions → Fees partial catalog, not Fees-certified scola_admission_fees_bridge auto_install=True. T0-E2 composite SC-ADM+SC-FEES expects the bridge. Live mixed dev/demo have both parents installed but the bridge uninstalled. Bridge only when both entitlements ON; Fees V1 must not require Admissions.
26 Bridge Fees → Finance NO No certified SC-FIN bridge. Accounting APIs currently live inside scola_fees. Explicit bridge or explicit exclusion of accounting from SC-FEES V1.
27 Notification failure semantics NO notification_service.py exists. Catalog: notification is DEC-010, not a success signal. Recipients; block vs best-effort; retry; audit on failure.
28 Audit event minimum NO Tracking fields exist on some models. No signed event list for create/approve/pay/verify/refund. Actor, acting-role, before/after amount, reason.
29 Disabled entitlement behavior NO Dev: scola_fees installed, flag OFF. Demo: flag ON. FE financeApp.js comment: SPP section “always visible”; app package: "SC-FIN"; no app-level moduleKey. Registry prefixes exist with featureFlag: scola_fees. Installed ≠ entitled is unproven for Fees APIs. Installed-but-unentitled APIs/menus fail-closed; hiding is not authorization.
30 Native Odoo / account / payment alternate paths NO Native account.move / account.payment.register / OpenEduCat fees / /web/dataset / public gateway callbacks. RT-W10-NEG-01 BLOCKED. All native/legacy paths fail-closed or explicitly excluded.

Signed platform decisions that exist (do not invent around them)

Decision Status Implication for T6B
DEC-001 bounded Core Approved / RC1-A certified SC-FEES is optional. Core smoke must not own W10 business tests.
DEC-003 atomic capabilities Approved as Core control View ≠ manage ≠ receive_cash ≠ verify ≠ post ≠ refund. Prefix /api/v1/finance/ collapsing mutations to finance.billing.view contradicts DEC-003 until split.
DEC-014 credential lifecycle Frozen V1 Fees must not introduce caller-chosen passwords, raw tokens, or native reset. Fees mapping for payer accounts is still unsigned.
DEC-004 maker-checker Unsigned for Fees Blocks items 5, 9, 10, 19.
DEC-008 master data / effective dates Unsigned for Fees Blocks items 1, 2, 24.
DEC-010 notification Catalog-referenced, Fees mapping unsigned Blocks item 27.
T6A W03 contract Certified independently for ADM only Does not approve Admission→Fees billing, scholarship, or payment.

Questions requiring owner approval

Copy-ready for Finance/Billing Product Owner + School Treasurer SME + Security/DPO:

  1. Who owns fee products, rules, and templates, and is that owner SC-FEES rather than SC-FIN?
  2. How do effective dates and in-force rule changes work for already-billed enrollments?
  3. Which student/enrollment records may be billed, including company scope?
  4. What is the tenant predicate for student, course, batch, fee, invoice, payment, journal, and bank?
  5. What is the maker-checker matrix for create/approve/post/verify/reject/refund/reversal, including self-approval?
  6. Who may view a student balance?
  7. Confirm parents see only active linked children.
  8. Confirm students see only self billing.
  9. What may cashier vs treasurer mutate?
  10. May school admin post/verify, or only configure?
  11. Which payment channels are in V1?
  12. What is the manual cash/transfer evidence and posting contract?
  13. Which gateways, signatures, and replay rules are in V1?
  14. What is the proof attachment type/size/scan/download/retention policy?
  15. What are the idempotency keys and unique constraints?
  16. What are gateway timeout, retry, and dead-letter states?
  17. How is overpayment handled?
  18. Are partial payments allowed, and how is remaining balance recomputed on the server?
  19. What is the refund/reversal workflow and predecessor-state table?
  20. What is the failed-payment recovery contract?
  21. When is a receipt issued, and is it idempotent?
  22. Does a Fees payment create a journal, and which company journal?
  23. Is accounting posting in SC-FEES V1, an SC-FIN bridge, or excluded?
  24. Who owns scholarship/discount/installment, and how are negative balances prevented?
  25. Confirm Admission→Fees is a separately entitled bridge, not a Fees prerequisite.
  26. Confirm Fees→Finance is a separately entitled/certified bridge or excluded from V1.
  27. Does notification failure block the financial transaction?
  28. What audit events are mandatory?
  29. What is the installed-but-unentitled and package-OFF contract?
  30. Which native Odoo/OpenEduCat/account/payment paths are excluded and fail-closed?

Until those answers are signed and immutable, engineering must not implement “the current code path” as the approved W10 lifecycle.

Current approval

The requesting user approved all 30 recommended decisions on 2026-08-17. The signed decision record is T6B-FEES-approved-product-contract.md. The historical NO entries above are preserved as the pre-approval snapshot; implementors must use the approved contract for all subsequent work.

Containment note

Phase 2 permits containing an unsafe surface only when that containment follows an existing security/package contract.

DEC-003 already forbids capability collapse and STAB-014 already forbids unscope elevated IDs. Choosing a refund, posting, or gateway lifecycle from current controllers would itself invent items 13, 19, 22, and 23. Therefore this tranche did not change application code. Findings are recorded, not silently “fixed” into a new financial lifecycle.