Skip to main content

Observations — Commercial Inspection & Verification Model

Status​

Active – Commercial-Native Implementation (core flows implemented; UI/offline pending)

Purpose​

Observations in Evalium are a verification mechanism, not an educational assessment.

They are designed to support professional service delivery where a human actor must verify that work, behaviour, or conditions meet a defined standard — and where the output must be defensible months or years later.

This includes (but is not limited to):

  • Health & Safety inspections
  • ISO / compliance audits
  • Site walkthroughs
  • Practical competence verification
  • Internal quality checks
  • Consultant-led or client-performed inspections

Observations are optimized for speed in the field, clarity of findings, and immutability after sign-off.


Core Concept​

An Observation is a structured inspection consisting of:

  • A Rubric (what to check)
  • One or more Subjects (who or what is being checked)
  • Findings (issues identified)
  • Evidence (photos, video, notes)
  • A Review & Approval workflow
  • An immutable snapshot once approved

Observations do not primarily produce scores. They produce defensible findings.


Implementation Status (Current)​

  • Findings enforcement is live: requiresComment and requiresEvidence are enforced during answer/evidence capture, and finding.detected ledger events are emitted on submit.
  • Evidence handling reuses the shared evidence ledger flows (standalone, inline, mixed).
  • Submission review/approval workflow is implemented at the API layer (approval status + approve/reject + request-changes + reopen endpoints); four-eyes enforcement is live via reviewPolicy on evaluation versions (self_approve default) and optional auto-approve via autoApprove.
  • Subject/asset model (Option A) is implemented with org/tenant scoping; assignment-based visibility is implemented via assignment_subjects + assignment-target read policy for external inspectors.
  • Findings projection is live: reporting.report_findings is populated by the reporting projection worker for dashboards and filters, and reporting exposes findings list APIs with ledgerEventId for claims/disputes linkage.
  • Batch mode UX is planned; execution currently remains one session + one submission per subject.

Technical Implementation Notes (How It Works)​

  • Findings enforcement: rubric metadata is validated at answer/evidence capture; on submit, findings emit finding.detected ledger events and are projected into reporting.report_findings.
  • Evidence handling: evidence metadata and decisions flow through the shared evidence ledger (evidence.* events) for standalone, inline, and mixed paths.
  • Review/approval: submission approval status is persisted; reviewPolicy (self_approve | four_eyes) and autoApprove are stored on evaluation versions and enforced at approval time. Review actions (request_changes, reopen) update approval status and emit ledger events.
  • Subjects/assets: subjects, subject_users, assets, assignment_subjects, and submission_subjects are tenant/org scoped and protected by RLS with assignment-based visibility for inspectors (assignment target can read their assignments across org scope).
  • Batch grouping: batch_id is canonical on assignments and copied to submissions at submit-time; submissions expose batchId for reporting without joining scaffolding.
  • Subject auto-link: when an assignment carries a subjectId, the submission inherits it at submit-time (no manual attach required).
  • Findings list API: reporting exposes /reporting/findings?submissionId=... with ledgerEventId to anchor claims/disputes to a specific finding event.

Functional Flow (What Users Experience)​

  • Inspector completes checks; any finding with requiresComment/requiresEvidence blocks progress until satisfied.
  • Evidence upload and approval reuse the same ledger-based evidence flows used elsewhere.
  • Submissions enter pending_review unless autoApprove is enabled; four-eyes prevents self-approval when configured.
  • Subjects are visible only when scoped by org or linked via assignments/submissions the inspector can access; external inspectors see subjects once an assignment is issued.
  • Batch UI groups multiple assignments; each subject still yields its own session + submission, with a shared batchId.

Terminology Mapping​

Educational TermCommercial Meaning
Student / CandidateSubject (Person, Asset, Location)
Group SessionBatch / Site / Audit Mode
ObserverInspector / Auditor
CriterionCheck / Control
ScoreStatus / Finding
FinaliseSubmit for Review
ResultOutcome
PortfolioEvidence Pack

Observation Structure​

1. Observation Template​

Defines what is inspected.

Includes:

  • Title & description
  • Rubric items (checks)
  • Optional severity metadata
  • Required evidence rules
  • Review configuration (self-approve vs four-eyes, optional auto-approve)

Templates are reusable across clients and sites.


2. Subjects (Who or What Is Observed)​

A Subject represents the entity being inspected.

Examples:

  • A person (employee, trainee)
  • A location (room, site, warehouse)
  • An asset (vehicle, machine, extinguisher)

Important: Subjects are treated generically in the system. They may be users today and assets later without changing the Observation model.


Actor vs Subject (Non-Negotiable)​

Observations must separate:

  • Actor = the person who performed/logged/approved the work (a user)
  • Subject = the entity being inspected (person, asset, or location)

This keeps the ledger clean when a record is about a non-person entity (e.g., a fire extinguisher or a room).


Subject / Entity Layer (Implemented)​

To support assets as first-class subjects without overloading users, introduce a Subject abstraction.

  • subjects (core, tenant/org scoped)
    • id, tenant_id, org_unit_id
    • subject_type (user, asset, later location, etc.)
    • display_name, external_ref, status, created_at
  • subject_users (optional 1:1 mapping when subject_type is user)
    • subject_id, user_id
  • assets (typed extension)
    • subject_id, asset_type_id, optional identifiers/metadata
  • assignment_subjects (planning link)
    • assignment_id, subject_id, role, relationship
  • submission_subjects (ledger link)
    • submission_id, subject_id, role (primary/secondary)

Why this fits Evalium:

  • Submissions remain the WORM truth; subjects are joinable context.
  • Assets can be mutable scaffolding without compromising ledger integrity.
  • Enables asset timelines, Glass Box views, and multi-subject audits.

Current state: Subjects, assets, assignment links, and submission links are implemented with RLS-scoped tables (org/tenant scope + assignment-based visibility for inspectors).

Technical Implementation​

  • Tables: subjects, subject_users, assets, assignment_subjects, submission_subjects.
  • RLS: subject visibility checks org scope or assignment linkage; submission subject access mirrors submission visibility.
  • Assignments can attach a subject via assignment_subjects, enabling just-in-time read access for inspectors.

Functional Flow​

  • Admins create subjects (users or assets) in their org.
  • Assignments link to subjects for inspection tasks.
  • Inspectors can only see subjects tied to assignments they can access or submissions they can view; assignment targets can read assignments even when org scope differs.
  • Submissions inherit assignment subjects automatically on submit to preserve execution attribution.

Batch / Audit Mode (Formerly Group Sessions)​

Batch Mode allows one inspector to apply the same rubric across many subjects in one flow.

Examples​

  • 30 fire extinguishers
  • 20 desks
  • 12 delivery vehicles
  • 10 staff members

Key Properties​

  • Grid-based UI
  • Fast sequential completion
  • Shared context (same site, same visit)
  • Single submission per subject
  • Unified review & approval layer

This is a core differentiator versus tools that require opening a new report per item.

Implementation Note (Current)​

Batch mode is UI orchestration rather than a multi-submit DB primitive. Each subject still maps to its own session + submission to preserve the execution ledger invariant.

Technical Implementation​

  • assignments.batch_id is the canonical planning handle.
  • submissions.batch_id is copied at submit-time for immutable execution context.
  • submission.batchId is exposed in API responses for reporting and Glass Box filters.

Functional Flow​

  • A batch action creates multiple assignments with a shared batchId.
  • Each assignment produces a separate session/submission.
  • Post-execution reporting uses batchId from submissions without joining assignments.

Findings (First-Class Concept)​

Definition​

A Finding is a rubric outcome that indicates:

  • Non-compliance
  • Risk
  • Required action

Findings are recorded as rubric outcomes enriched with structured metadata. Ledger truth remains on submissions/items, while reporting uses a projection for filtering.

Implementation​

Each rubric option may include metadata such as:

{
"severity": "critical",
"requires_evidence": true,
"requires_comment": true
}

Behaviour Rules​

When a Finding is triggered:

  1. UI visually escalates (colour/state)
  2. Evidence upload is forced
  3. Comment / remediation note is forced
  4. Item is added to the Action Required Summary

Implementation note: Evidence and comment requirements are enforced at answer/evidence capture.

Findings are surfaced prominently in:

  • Reviewer dashboards
  • Client-facing summaries
  • Exported reports

Implementation note: Findings remain ledger-truth JSON on submissions/items; the reporting worker projects them into reporting.report_findings (including ledger_event_id) and reporting exposes a findings list API for claims/disputes linkage.

Technical Implementation​

  • Findings metadata lives in item payload/rubric and is enforced during answer/evidence capture.
  • On submit, finding.detected ledger events are emitted for projection.
  • Reporting worker projects findings into reporting.report_findings for dashboards/filters (with ledger_event_id).
  • Reporting API exposes /reporting/findings?submissionId=... for downstream claims/disputes.

Functional Flow​

  • A failed check with severity produces a visible finding and blocks approval without required evidence/comment.
  • Reviewers see findings surfaced in summaries and Glass Box views.

Integration Risk Controls (Mitigations)​

1) Subject RLS & External Inspectors​

Subjects use org/tenant scoping plus assignment-based, just-in-time visibility: if an inspector has an assignment tied to a subject (active or completed), or a submission they can see, they can read the subject even when the inspector is not in the subject's org unit.

2) Batch Mode vs Session Invariant​

Batch mode will not create many submissions inside one session by default. If bulk commit is ever required, it will be wrapped in a single TxManager transaction and each submission will remain an independent ledger record.

3) Findings Projections​

Findings remain ledger-truth JSON, but reporting is driven by a projection: finding.detected ledger events are emitted and reporting.report_findings is populated for dashboards and filtering.


Evidence Capture (Speed Is Non-Negotiable)​

Evidence is an attribute of any rubric item.

Supported Evidence​

  • Photos (multi-shot)
  • Video clips
  • Files
  • Free-text notes

Field Ergonomics (Required)​

  • Tap → Snap → Snap → Done
  • No file browser dependency
  • Offline-first capture where possible

Forensic Enhancements​

  • Automatic timestamp watermarking
  • Optional GPS stamping (if available)
  • Evidence bound to rubric + subject + visit

Evidence is immutable once the submission enters review.


Submission Lifecycle​

Observations produce a Submission, shared with Knowledge and Evidence workflows.

Status Fields (Orthogonal)​

FieldPurpose
lifecycle_statusin_progress → completed
outcomepass / fail / pending
approval_statusapproved / pending_review / rejected / changes_requested

Implementation note: approval_status is persisted and updated by review endpoints; approvals are only allowed from pending_review, request-changes is only allowed from pending_review, and reopen is allowed from approved/rejected/changes_requested; reviewPolicy enforces four-eyes when configured.

Technical Implementation​

  • approval_status is stored on submissions and updated via review handlers.
  • reviewPolicy + autoApprove are stored on evaluation versions and enforced during submission approval.

Functional Flow​

  • Inspectors submit; submissions land in pending_review unless auto-approve is enabled.
  • Reviewers approve/reject; status transitions are immutable and auditable.

Review & Approval (Universal Workflow)​

Observations default to pending review unless configured otherwise.

Implementation note: Approval APIs are live (approve/reject/request-changes/reopen); four-eyes enforcement is implemented via reviewPolicy. Auto-approve is supported via autoApprove on evaluation versions.

Technical Implementation​

  • Approval endpoints write ledger events and update approval_status.
  • Four-eyes enforcement rejects self-approval when reviewPolicy=four_eyes.
  • Auto-approve runs at submit-time and emits submission.approved.
  • Request-changes/reopen emit submission.changes.requested and submission.reopened.

Functional Flow​

  • SMB flow: self-approve or auto-approve for low friction.
  • Regulated flow: approval requires a distinct reviewer identity.

Standard Workflow​

  1. Inspector completes observation

  2. Submission enters pending_review

  3. Reviewer is notified

  4. Reviewer:

    • Views immutable snapshot
    • Reviews findings & evidence
  5. Reviewer approves → approved

  6. Submission becomes client-visible

Rejection / Change Request​

If rejected or changes are requested:

  • Submission status updates to rejected or changes_requested
  • Review action emits a ledger event with optional reason metadata
  • Review can be reopened to return the submission to pending_review
  • If rework is needed, a new session/submission is created (no edits to the original)

Four-Eyes Principle (Configurable)​

Evalium supports both:

SMB Mode​

  • Inspector can self-approve
  • Zero friction

Enterprise / Regulated Mode​

  • Inspector cannot approve own work
  • Reviewer role enforced via capabilities
  • Full audit trail of approvals

This is controlled via:

  • Capabilities (submissions.approve)
  • Evaluation version reviewPolicy (self_approve | four_eyes)
  • Evaluation version autoApprove (default false)

Technical Implementation​

  • reviewPolicy and autoApprove are persisted on evaluation versions.
  • Approval handler validates actor vs submission owner when reviewPolicy=four_eyes.
  • Auto-approve sets approval_status=approved on submit and emits ledger events.

Client Visibility Rules​

Clients:

  • Only see approved submissions
  • Never see drafts or rejected work
  • See findings + evidence + timestamps
  • Receive a clean, defensible view

This protects consultant credibility.


Immutability & Audit Readiness​

Once approved:

  • Submission content is immutable

  • Evidence cannot be altered or removed

  • Approval metadata is preserved:

    • Who approved
    • When
    • From which role

This forms the Chain of Custody required for:

  • Regulatory audits
  • Client disputes
  • Insurance reviews

Non-Goals (Explicit)​

Observations are not:

  • Journals
  • Reflective diaries
  • Narrative learning logs

Those patterns belong to education and are intentionally out of scope for commercial inspections.


Outstanding / Planned​

  • Batch UI orchestration (grid capture + navigation across many subjects). Assignment batch helper exists; UI orchestration pending.
  • Offline capture + sync (separate macro-level initiative).
  • Subject bulk import UI + richer search/filtering in UI (API supports assetType/tags/identifiers and returns asset fields on list; UI pending).
  • Claims/disputes UX flows that consume findings + review actions (backend linkage is ready; UI pending).

Proof Runs (Implemented)​

  • backend/tests/test_observations_all.sh — observation end-to-end suite.
  • backend/tests/observation_subject_visibility_assignment.sh — assignment-based subject visibility (external inspector).
  • backend/tests/observation_subjects_import.sh — subject import preview/commit (API).
  • backend/tests/observation_subjects_filtering.sh — subject list filters (assetType/tags/identifier fields).
  • backend/tests/observation_findings_evidence_required.sh — findings evidence gating + findings projection.
  • backend/tests/observation_submission_approval.sh — approval lifecycle (approve/reject/request changes/reopen).
  • backend/tests/observation_submission_auto_approve.sh — auto-approve path.
  • backend/tests/observation_submission_four_eyes.sh — four-eyes enforcement.
  • backend/tests/observation_verification_context_required.sh — L4 verification context + step-up enforcement.
  • backend/tests/observation_batch_assignments.sh — batch assignment to submissions with batchId.
  • backend/tests/observation_batch_assignments_bulk.sh — assignment batch helper (one assignment per subject, shared batchId).
  • backend/tests/observation_assignment_multi_subjects.sh — multi-subject submission linkage.
  • backend/tests/observation_assignment_subject_auto.sh — auto-link submission subjects from assignment scope.

Summary​

Observations in Evalium are:

  • Inspection-native
  • Finding-driven
  • Evidence-first
  • Review-gated
  • Legally defensible

They transform:

“I checked this” into “I can prove I checked this, correctly, on this date, with this evidence.”

This is the foundation that supports premium pricing, professional trust, and scalable service delivery.