Lewati ke isi

T6A W03 Approved Product Contract

Field Value
Approver Requesting user via current conversation
Date 2026-08-16
Scope SC-ADM / W03 only
Status APPROVED_BY_REQUESTING_USER_CONVERSATION
RC1 impact None. RC1-A bounded Core remains certified and unchanged.
Production authority None
Ancestor T6A-W03-product-decision-gate.md T6A-B (2026-08-16) — historically correct when issued

This record is the immutable W03 product contract for engineering. It does not rewrite T6A-B. It does not certify SC-ADM. It does not authorize production or GBN change.

Related signed platform decisions that this contract binds rather than weakens: DEC-001, DEC-003, DEC-014. For the Admissions domain only, this record also supplies the missing DEC-004 (maker-checker) and DEC-008 (master-data / effective dates) answers listed below.


1. Identity

  • Login identity: normalized email, unique within the database.
  • Applicant person: (company_id, NIK).
  • NISN is a secondary unique identity when present.
  • Application: unique (company_id, admission_register_id, applicant_person_id).
  • KK and parent email are not applicant-person identity keys.
  • Pre-NIK draft uses an opaque expiring registration UUID.
  • One authenticated parent account may own multiple applicant persons only through an explicit verified relationship.

2. Application state machine

Canonical states: draft, submitted, correction_required, verified, accepted, rejected, withdrawn, enrolled.

Allowed transitions:

Actor From To
applicant draft submitted
applicant correction_required submitted
applicant any non-enrolled applicant-owned state withdrawn
verifier submitted correction_required
verifier submitted verified
approver verified accepted
approver verified rejected
manager with reason rejected submitted
manager with reason, before enrollment accepted verified
enrollment officer accepted enrolled

enrolled is terminal inside W03. Post-enrollment correction belongs to W02.

Applicant lifecycle fields (scola.spmb.applicant.state / lifecycle_stage) may remain only as derived projections during migration. They must not remain an independent authoritative state machine. Authoritative application state is w03_state on the application record.

Illegal, skipped, backward, repeated, late, and unauthorized transitions fail closed with zero mutation.

3–4. Roles and separation of duty

Acting roles:

  • Applicant: own draft/edit/upload/submit/correct/withdraw/status.
  • Admissions Viewer: read only.
  • Admissions Verifier: document verification and submitted → correction_required|verified.
  • Admissions Approver: verified → accepted|rejected only.
  • Enrollment Officer: explicit accepted → enrolled only.
  • Admissions Manager: configuration and controlled reopen (rejected → submitted, accepted → verified with reason).
  • School Admin receives no approve/enroll authority merely from being school admin.

Rules:

  • last verifier cannot final-approve the same application;
  • final approver cannot enroll the same application;
  • self-approval denied;
  • no customer break-glass;
  • acting-role/session authority, never assigned-role union.

V1 engineering binding to existing Scola acting roles

The conversation named W03 acting roles, not new login personas. V1 binds them as follows (capabilities, not wildcards):

W03 acting role V1 Scola acting role
Applicant pendaftar
Viewer principal, vice_principal_public_relations (view only)
Verifier admin_staff, head_admin
Approver vice_principal_student_affairs
Enrollment Officer admin_staff, head_admin
Manager school_admin (config + reopen; no verify/approve/enroll)

SoD is enforced per application even when one login may hold verifier and enrollment-officer capabilities.

5. Quota

  • Reserve quota atomically at verified → accepted.
  • Count accepted + enrolled.
  • Hold row/advisory transaction lock until commit.
  • Concurrent last-seat: exactly one success.
  • Default public projection is open/full.
  • Exact capacity requires explicit publish_capacity=True.

6–7. Student handoff

  • Student creation happens only on explicit accepted → enrolled.
  • Invoked only by Enrollment Officer.
  • No cron, notification, applicant CTA, acceptance action, Fees, CBT, or Foundation callback may create a student.
  • Student creation, parent link, W03/W02 source link, and application transition must be one authoritative transaction.
  • Post-enrollment correction belongs to W02.
  • Failed enrollment returns failure and leaves the application accepted.

8. Idempotency

  • Require Idempotency-Key on W03 mutations.
  • Persist company, actor, operation, request hash, response/result, and timestamps.
  • Application uniqueness: (company_id, admission_register_id, applicant_person_id).
  • Enrollment business key: spmb:<company_id>:<application_id>:enroll.
  • Student/W02 record must have a unique SPMB source reference.
  • Search-then-create alone is insufficient. Use constraints or conditional updates.

Same key + same payload: return the original authoritative result. Same key + different payload: reject.

9. Recovery

  • Submitted applications are immutable except through correction_required.
  • Failed enrollment returns failure and leaves application accepted.
  • One durable queue/outbox with unique jobs for retry and recovery.
  • Remove per-record dynamic cron creation.
  • Retry is idempotent.
  • Never delete audit history.
  • W03 must not delete an enrolled Core student.

10. Configuration

Atomic capabilities, at minimum:

  • admissions.<resource>.view|create|edit|delete
  • admissions.application.verify
  • admissions.application.approve
  • admissions.application.reopen
  • admissions.application.enroll

No mutation may use a .view capability. All records and foreign keys are company-scoped. Referenced config cannot be hard-deleted; archive or version it. Material configuration changes use effective dates and before/after audit.

11. Documents

  • Allow PDF/JPEG/PNG; maximum 10 MiB per file; maximum 20 files per application.
  • Validate extension, MIME, and magic signature.
  • Private storage and unguessable storage key.
  • Malware scan/quarantine before verification/download.
  • Applicant replacement/deletion only in draft or correction_required.
  • Download only for owner or assigned tenant-scoped Admissions staff.
  • Retention: abandoned draft 90 days; rejected/withdrawn 12 months; enrolled decision/audit 5 years; avoid duplicate W03/W02 document retention.
  • Batched retention jobs with audit tombstones, not one cron per record.

12. Public protection

  • Replace all public prefix matching with exact path + method declarations.
  • Registration/OTP: 5 requests/hour per IP and normalized identity.
  • Verification: 5 attempts per token.
  • Status: 30 requests/minute and requires authenticated session or application number plus opaque secret.
  • Generic response shape for existing, missing, duplicate, disabled, and blocked identities.
  • CAPTCHA/challenge may activate after threshold.
  • Public quota returns open/full by default.

13. Notifications

  • Notifications are non-authoritative.
  • Transactional outbox, dedupe key, bounded retry, operator-visible failures.
  • Notification failure does not roll back acceptance/enrollment.
  • Activation remains incomplete until OTP/token verification.
  • No sensitive PII or secrets in subject, response, audit, or logs.

14. Bridges

  • Base SC-ADM must work without SC-FEES, SC-ASSESS, or SC-FOUND.
  • Fees/payment/invoice → Fees bridge; test/CBT → Assessment bridge; Foundation → Foundation bridge.
  • Base APIs return feature_disabled or are absent when the bridge entitlement is missing.
  • Internal bridge auto-install is allowed only when both parent modules exist.
  • Runtime execution additionally requires both parent entitlements.
  • Each bridge has a separate suite and is not certified by T6A.
  • Complaints remain excluded and fail-closed.

15. Applicant credentials (DEC-014 mapping)

Canonical flow:

registration request → email OTP verification → purpose-bound activation token → applicant chooses first password → account activation

Rules:

  • registration request does not accept a password;
  • no active user before successful verification;
  • activation token follows DEC-014: hash-at-rest, high entropy, TTL, single-use, purpose/user bound, supersession, no raw logging;
  • applicant may choose their first password only after activation-token proof;
  • remove dual /api/SPMB/account/register;
  • remove public link-by-email;
  • existing parent must authenticate and explicitly attach an applicant relationship;
  • SPMB OTP remains separate from password-reset tokens;
  • native Odoo signup/reset remains denied;
  • /my/admission* must not remain a second mutation lifecycle — safe GET may redirect to canonical /spmb, CUD must be absent/410;
  • forgot/change/admin reset remain canonical DEC-014 flows.

Non-goals (unchanged)

Fees/CBT/Foundation certification, complaints, messaging, W01/W02 redesign, Core navigation redesign, production promotion, GBN mutation.