Skip to content
FEAT-PROD-002: Record Hall Pass Log

FEAT-PROD-002: Record Hall Pass Log

Reference Number Version Effective Date Supersedes Authority Level
FEAT-PROD-002 1.1 2026-10-01 1.0 Normative

Revision 1.1 (2026-10-01; ratified by the owner 2026-10-01): adds §III.A, resolution of a pending hall-pass request (approve, reject, student cancel) held in pending_actions (DOM-STORE-001 5.3 §IX). §III is unchanged.


I. Purpose

This FEAT records approved hall-pass rows for the Productivity and Payroll domain.

It writes to hall_pass_logs and reads class-configuration-owned hall_pass_settings to determine whether the pass may be granted.

The row represents the approved hall-pass instruction and the entitlement-consumption event at the same time.

This FEAT uses CanonicalContext for live request authority and the canonical temporal resolver for request-time stamping.


II. Execution Context

1. Required Inputs

  • ctx: CanonicalContext
  • destination: teacher-prescribed hall-pass destination
  • requested_by_seat_id: seat requesting the pass
  • approved_by_seat_id: seat approving the pass
  • reference_time_utc: optional explicit timestamp for deterministic evaluation

2. Canonical Authority

  • ctx.class_id provides the class boundary
  • ctx.seat_id provides the approving seat for live teacher actions
  • ctx.actor_role MUST be teacher or another lawful approving authority

The FEAT MUST not infer approval authority from the destination or hall-pass payload.


III. Canonical Write

record_hall_pass_log(...)

This is the only lawful mutation path for hall_pass_logs.

Typical use cases:

  • teacher approves a hall pass request
  • teacher issues a hall pass directly

Rules:

  • MUST require class_id, requested_by_seat_id, approved_by_seat_id, and destination
  • MUST evaluate class-scoped hall_pass_settings before writing the approved pass
  • MUST NOT mutate hall_pass_settings; mutation of that table belongs to Class Configuration
  • MUST fail closed if settings disable the requested destination
  • MUST fail closed if queue or simultaneous limits are reached
  • MUST record the request timestamp in class canonical time
  • MUST represent approval and entitlement consumption together
  • MUST set hall_pass_logs.hall_pass_id to the consumed entitlement instance entitlement_id
  • MUST set hall_pass_logs.correlation_id to the consumed entitlement’s source correlation_id
  • MUST not record exit time
  • MUST not record return time
  • MUST not record hall-pass elapsed time
  • MUST not derive attendance state from the hall-pass row

Execution steps:

  1. Resolve CanonicalContext and confirm the approving actor is lawful for the class.
  2. Resolve CLE with canonical_temporal_resolver("CLE", primitive="current_time", canonical_execution_context=ctx, reference_time_utc=reference_time_utc).
  3. Validate the requested seat, approving seat, and destination.
  4. Read Class Configuration’s hall_pass_settings for the class and evaluate pass-type enablement plus queue/simultaneous limits.
  5. Consume one available entitlement instance through the entitlement service.
  6. Record the approved hall-pass row in hall_pass_logs with the consumed entitlement’s entitlement_id in hall_pass_id and its source correlation_id.
  7. Return the approved hall-pass instruction as the lawful source for later attendance-session exit/return evidence.

Failure conditions:

  • missing approval authority
  • missing entitlement grant identity
  • invalid class or seat boundary
  • hall-pass settings prohibit the requested pass
  • queue or simultaneous limits are reached
  • attempt to backfill exit or return data into the hall-pass table

III.A Resolving a pending hall-pass request

A pending hall-pass request is a pending_actions row with authoritative_feat = FEAT-PROD-002 and payload kind hall_pass_request, submitted under FEAT-STOR-002 §X.A. This FEAT is its only resolver (DOM-STORE-001 §VII.B, §IX). Every resolution is scoped by ctx.class_id: a request in another class is not found.

Approve (teacher):

  1. Lock the request row with SELECT ... FOR UPDATE and delete it. A concurrent resolution of the same request waits on that lock and, once this transaction commits, finds no row. Exactly one approval therefore succeeds; every other attempt fails as not found. The FEAT idempotency key is not relied on for this.
  2. Record the pass through record_hall_pass_log(...) (§III) with the payload’s requested_by_seat_id and destination, the approving seat from ctx, and the entitlement consumption §III requires.
  3. Commit the deletion, the hall_pass_logs row and the pass consumption atomically.

If any step is refused (for example, no pass is available, or the settings prohibit the destination), the transaction rolls back and the request stays pending, unchanged, with its original submitted_at (DOM-STORE-001 §VII.B: a failed resolution leaves the pending action intact).

Reject (teacher): lock and delete the row. Nothing else is written; no pass is consumed.

Cancel (student): lock and delete the row only when its seat_id is the student’s own seat in ctx. Any other request is not found. Nothing else is written.

Reads of pending requests (teacher queue, dashboard, student status) take no lock and write nothing.


IV. Temporal Rules

  • Hall-pass request timestamps MUST be recorded in class canonical time.
  • Exit and return timing remain attendance-session concerns and are not stored here.
  • Any hall-pass display or comparison logic MUST use canonical temporal evaluation.

V. Invariants

  1. Hall-pass approval consumes entitlement.
  2. hall_pass_id links the hall-pass log to the specific consumed entitlement instance.
  3. The correlation ID links the hall-pass log to the entitlement source event.
  4. If the pass was purchased from Store, the upstream ledger entry uses the same correlation ID.
  5. The FEAT must fail closed if approval authority cannot be established.
  6. hall_pass_settings is a Class Configuration-owned input to the PROD grant decision and must be evaluated before writing hall_pass_logs.

VI. Dependencies

  • docs/DOMAIN/DOM-PROD-001_PRODUCTIVITY_AND_PAYROLL_DOMAIN.md
  • docs/FEATURE-EXECUTION/FEAT-CORE-000_FEATURE_EXECUTION_CONSTITUTIONAL_DIRECTIVE.md
  • docs/DOMAIN/DOM-OBL-001_OBLIGATIONS_DOMAIN.md
  • app/services/context_resolver.py
  • docs/SPEC/SPEC-TIME-001_CANONICAL_TEMPORAL_RESOLVER.md
  • app/utils/canonical_temporal_resolver.py
Edit canonical source on GitHub

Last updated: 2026-10-01