Phase 4 Verification and Private Evidence Engine¶
Purpose¶
Phase 4 implements DIREKT's first evidence-backed trust vertical slice. It does not create a blanket verified-provider state and does not authorize customer discovery. Each case evaluates one provider, one category requirement version and one scoped check.
Implemented boundaries¶
- provider organizations and category selections remain owned by Phase 3;
- evidence metadata lives in the private
evidenceschema; - verification cases, assignments, immutable recommendations, decisions, field visits and claims live in the
verificationschema; - original evidence bytes remain outside PostgreSQL behind
EvidenceStoragePort; - the checkpoint uses
SyntheticPrivateStorageAdapterand fictional metadata only; - private evidence object keys are opaque and never returned by API DTOs;
- provider routes require server-resolved provider scope;
- reviewer evidence access requires a global review permission and an active assignment to the exact case;
- every private access grant is short-lived, synthetic, watermarked and audited;
- safe claim cards exclude evidence objects, checksums, identifiers, reviewer identity, notes and private location data.
Evidence lifecycle¶
upload session requested
→ synthetic private object uploaded
→ completion and checksum confirmed
→ immutable evidence version created
→ ready for review
→ approved / rejected / correction required
→ replacement creates the next immutable version
→ approved evidence may later expire or be revoked
Evidence items may retain multiple versions. An update never rewrites an earlier version. Upload sessions bind provider, requirement, submitter, content type, size limit, consent and an opaque object key.
Verification case lifecycle¶
draft
→ awaiting evidence
→ ready for review
→ assigned
→ in review
→ approved / rejected / correction required / revoked
→ renewal, appeal, expiry or closure where permitted
Database triggers reject transitions outside the documented graph. A case binds:
- provider;
- category and immutable requirement version;
- specific requirement;
- check key and family;
- risk classification;
- policy version;
- evidence links;
- assignments;
- review and decision history;
- any resulting scoped claim.
Separation of duties¶
The database and application jointly enforce:
- provider creator cannot be assigned to review the provider;
- evidence submitter cannot review that evidence;
- reviewer, field-agent and supervisor assignments require their corresponding active platform role;
- finance has no review or decision permission;
- an operator must be actively assigned before case/evidence access;
- high-risk decisions require a prior recommendation from a different actor;
- field visits require a matching active field-agent assignment;
- recommendations, decisions and field visits are append-only.
Decision and claim derivation¶
Claims cannot be inserted or changed by ordinary SQL or application repositories. verification.record_decision(...) validates independence and assignment, records an immutable decision, changes the case/evidence state and derives a claim inside one transaction.
Every approved claim records:
- claim key and scoped statement;
- limitation;
- evidence/check family;
- checked timestamp;
- validity deadline;
- policy version;
- active, degraded, revoked or expired state.
No claim states that the provider is universally safe, competent or guaranteed to perform future work.
Expiry and revocation¶
verification.degrade_expired_claims(as_of) is deterministic and idempotent for a supplied timestamp. It:
- expires current evidence versions whose validity deadline has passed;
- expires active claims whose own deadline passed or whose linked evidence is expired/revoked;
- transitions approved cases to expired;
- records an append-only batch audit event.
Provider evidence revocation invokes the same degradation path so dependent claims cannot remain active.
API surface¶
Provider-scoped endpoints:
POST /api/v1/providers/{providerId}/evidence/upload-sessions
POST /api/v1/providers/{providerId}/evidence
GET /api/v1/providers/{providerId}/evidence
GET /api/v1/providers/{providerId}/evidence/{evidenceId}
POST /api/v1/providers/{providerId}/evidence/{evidenceId}/revoke
POST /api/v1/providers/{providerId}/verification-cases
GET /api/v1/providers/{providerId}/verification-cases
GET /api/v1/providers/{providerId}/claims
Operations endpoints:
GET /api/v1/operations/verification-queue
GET /api/v1/verification-cases/{caseId}
POST /api/v1/verification-cases/{caseId}/assignments
POST /api/v1/verification-cases/{caseId}/evidence/{evidenceId}/access
POST /api/v1/verification-cases/{caseId}/recommendations
POST /api/v1/verification-cases/{caseId}/decisions
POST /api/v1/verification-cases/{caseId}/field-visits
POST /api/v1/operations/verification/expire-claims
GET /api/v1/operations/providers/{providerId}/claims
No public evidence, case or evidence-object route exists.
Android checkpoint¶
The native Android app contains only fictional models and Compose cards for:
- private evidence versions;
- correction and resubmission history;
- verification timeline;
- scoped claim statement and limitation;
- deterministic expiry;
- explicit absence of real evidence and public discoverability.
The model uses epoch milliseconds rather than java.time so it remains compatible with minSdk 23 without adding desugaring.
Operations portal checkpoint¶
The Next.js portal contains a fictional verification queue and assigned-case summary. It deliberately omits:
- evidence files or real signed URLs;
- object keys and checksums;
- document identifiers;
- private addresses;
- download/export controls;
- public-publish controls;
- direct database/storage imports.
External integration handoff¶
When the dedicated DIREKT Supabase project is available, the synthetic adapter may be replaced by a Supabase private-storage adapter implementing the same port. That later change must add:
- private buckets and service-role backend access;
- signed upload/read URLs;
- MIME/signature/size verification;
- malware scanning and quarantine;
- lifecycle deletion and legal hold;
- integration tests against non-real fixtures.
No storage credential may enter Android, the browser bundle or the public repository.
Test obligations¶
The checkpoint must prove:
- evidence versions and decisions are append-only;
- direct claim insertion is rejected;
- provider self-review and evidence-submitter review are rejected;
- finance cannot recommend or decide verification;
- unassigned reviewers cannot access private evidence;
- assigned access is short-lived and audited;
- cross-provider evidence links fail;
- invalid state transitions fail;
- replacements preserve version history;
- claim output is safe and scoped;
- expiry and revocation degrade claims;
- no Phase 4 route creates public provider discovery;
- Android, portal and documentation contain fictional data only.
Explicit exclusions¶
- real provider evidence or personal data;
- production Supabase/storage credentials;
- production malware/document extraction services;
- real field-agent operations;
- public provider search or publication;
- maps, OTP, payment or authority integrations;
- production deployment and public pilot.