This page documents the governance spine that sits behind every Oshun V1
surface: the review package lifecycle that gates content and model releases,
the immutable audit and provenance layer that records what happened, and the
Trust & Safety subsystem that moderates content, assistant behavior,
persona/voice/avatar usage, generated media, support contact, and educational
integrity. It serves operators, reviewers, crisis-trained responders, and the
compliance/legal functions; in the V1 stack the deterministic policy and
state-machine cores live in @oshun/trust-safety, @oshun/review-persistence,
and @oshun/audit-platform, while the runtime enforcement (real classifiers,
live persistence, cross-domain fan-out) is the platform's job and is wired in at
the application boundary.
The honest framing up front: most of what this page describes is implemented
as deterministic, fully-tested pure-function and state-machine logic — the
policy taxonomy, severity SLAs, decision/appeal lifecycle, crisis cascade,
retention constants, and review state machine are real code with real exported
symbols. The things that are runtime responsibilities — the actual ML
classifiers that produce a PolicyHit, the durable append-only store that backs
the hash-chained audit log, the real Redis bus the crisis worker binds to — are
honest seams: the cores compute and validate, the runtime persists and enforces.
Where a capability is provider-gated or runtime-owned, this page says so.
Companion pages. The privacy/consent/DSAR/residency half of governance has its own page — Privacy, Consent, Data Portability, and User Controls — grounded in
@oshun/privacy. The customer-ops/entitlement/billing half lives in Support, Entitlements, Billing, and Customer Operations and Crypto Payments — Non-Custodial Entitlement Settlement, grounded in@oshun/billing-supportandlibs/aje/. This page focuses on the review, audit/provenance, and trust-and-safety layer and cross-links to those siblings where the boundaries touch. The architecture companion is Trust, Safety, and Privacy.
Where this sits in V1#
Three libraries carry the bulk of the governance logic, and they are deliberately separated by responsibility:
| Library | Package | Owns |
|---|---|---|
libs/shared/review-persistence |
@oshun/review-persistence |
Review package persistence, stage graphs, decision lifecycle, delegation, escalation, release-validity, artifact templates, prioritization, audit linkage |
libs/shared/audit-platform |
@oshun/audit-platform |
Immutable hash-chained audit log, retention, compliance attestations, exception approvals, provenance/rights, watermark verification, synthetic-media labeling, automation authority |
libs/oshun/trust-safety |
@oshun/trust-safety |
Policy taxonomy, severity/SLA, decision/appeal lifecycle, crisis cascade, abuse-pattern detection, operator dashboards, eval/release gates |
The split matters: a Trust & Safety SafetyDecision (a moderation verdict) is a
different object from a review-persistence ReviewDecision (a creator/editorial
approval). Both record rationale, both emit audit events, both have appeal/
override lineage — but they govern different flows. Review packages gate what
gets published; Trust & Safety governs what gets enforced after publication or
during a session.
Part 1 — Review, Audit, Compliance, Rights, and Provenance#
This is the editorial/operator-facing governance layer. It is the machinery that lets a piece of content, a model, or a generated artifact move from "submitted" to "released" with a recorded, defensible decision trail behind it.
Review packages and the decision lifecycle#
A review package is the unit of governed release.
@oshun/review-persistence persists packages, their stage graphs (each
package moves through one or more ordered stages), and a decision lifecycle
that the DecisionLifecycleService (decision-lifecycle.ts) orchestrates over
the repository primitives. The service is composed entirely from
ReviewPackageRepository methods — it never reaches into the underlying store —
so any backend implementing the repository interface (the in-memory test double
in in-memory.ts, or the Prisma-backed production store) behaves identically.
The lifecycle enforces the ADR-0029 rules in real code:
- Outcomes are constrained. A
ReviewDecision.outcomeis one ofapproved,rejected, orchanges_requested— theOUTCOME_TO_TERMINAL_STAGE_STATEmap translates each non-approval outcome into the matching terminal stage state (approved→approved,rejected→rejected,changes_requested→changes_requested). - Threshold approvals.
decideNextStageStateincrementscurrentApprovalson eachapproveddecision and only moves the stage toapprovedwhencurrentApprovals >= requiredApprovals— so a two-signoff stage genuinely requires two approvals before it finalizes. - Rationale and attribution are mandatory. Every
ReviewDecisionrecordsrationale,decidedById, anddecidedRole. - Override preserves lineage.
recordOverridemarks the prior decisionfinal: false(superseded) and records the new decision withpriorDecisionIdset, so the chain is never lost. - Reopen preserves lineage.
recordReopenclears the prior decision'sfinalflag, transitions the stage back toin_review, resetscurrentApprovalsto 0, and appends areopendecision carryingreopenedFromDecisionId. By convention a reopen recordsoutcome: 'changes_requested'because the stage is back in active review. - Every decision emits a structured audit event. Each transition appends a
ReviewPackageAuditEventwithaction: 'review.decision_recorded',outcome: 'success', and the actor/stage/decision references — the audit linkage is not optional bookkeeping, it is part of the same atomic write.
The repository surface (types.ts) gives operators the queue they actually
work: ReviewPackageFilter narrows by primaryDomain, touchesDomain,
status, priority, artifactType, releaseChannel, escalated,
governanceTagged, free-text search, and time windows; ReviewPackageSort
orders by priority (critical-first per the PRIORITY_WEIGHTS map —
critical: 3, high: 2, medium: 1, low: 0) or recency; and ReviewPackageList
returns cursor-paginated results with a stable total so the UI can render
queue depths. Cursor pagination is chosen deliberately — operator queues are
deep and ordered by recency, and cursors stay stable under concurrent writes
where page offsets would skip or repeat rows.
The package also carries release validity (release-validity.ts),
delegation policy (delegation-policy.ts), stage-graph assembly
(stage-graph-assemble.ts), artifact templates (template-registry.ts),
and audit linkage (linkage.ts) — the full set the features backlog calls
out for governed artifact release.
Immutable audit, hash-chaining, and retention#
@oshun/audit-platform is the system of record. Its defining property is
tamper-evidence via a hash chain (hash-chain.ts): every audit event
produces a chain entry of the form
eventHash = sha256(canonicalSerialize(event))
entryHash = sha256(previousChainHash || eventHash)
(using @noble/hashes for the SHA-256 primitive). Chain entries live in an
append-only sidecar log (AuditChainLog); verifying a range re-runs the chain
forward from an anchor and compares, surfacing an AuditChainMismatch
(chain-hash-mismatch and friends) and raising AuditChainTamperDetectedError
at the exact position any record was altered. The store-layer append-only
guarantee is the first line of defense; the hash chain is the second.
Retention (retention.ts) is a real policy service, not a constant table:
RetentionPolicyService evaluates each record against a RetentionPolicy,
classifying it into a RetentionTier (hot | warm | cold |
past_retention) with a RetentionRedactionMode (none | pii | full), and
produces a RetentionSweepReport. A record under legal hold "stays hot forever
until the hold is lifted" — the retention sweep cannot age out held data.
Compliance attestations (compliance-attestation.ts) model a real
attestation workflow: an AttestationDefinition with a cadence and a scope
(global | per-domain | per-tenant), AttestationEvidenceRequirements, an
AttestationRun that moves through statuses, signed AttestationSignatures,
and an AttestationDecision of approved | approved_with_findings |
rejected. computeClosureHash seals a completed run. Exception approvals
(exception-approval.ts) provide the documented escape valve when a control
must be waived, with its own approval trail.
Human-in-the-loop authority and mandatory approval#
The features backlog calls for human authority rules, automation classifications, and mandatory human approval — and they are real:
- Automation authority (
automation-authority.ts) defines anAutomationPostureperArtifactClass, modulated by aSensitivityContext(Audience∈internal | partner | public,DistributionScale∈dev | staging | production) throughAutomationPolicyContextMultipliers. TheAutomationPolicyRegistryresolves anAutomationDecision— i.e. how much of a release may be auto-finalized vs. must route to a human — based on what is being released and how widely. - Mandatory human approval (
mandatory-human-approval.ts) is a hard gate: aMandatoryHumanApprovalGateproduces aFinalizationDecisionofallowedorblocked, with aFinalizationBlockReasonwhen a requiredHumanApprovalRecord(signed by aHumanApprovalSigner) is absent. The integration testblocked-auto-finalization.integration.spec.tsexists precisely to prove the block fires. - Manual override (
manual-override.ts) lets an authorized operator override an automated outcome with rationale, andescalation-rules.tsencodes when a package must escalate.
Rights, provenance, and synthetic-media labeling#
The provenance layer attaches verifiable claims to generated media and verifies them on the way back out:
- Provenance attachment (
provenance-attachment.ts) and source-asset lineage (source-asset-lineage.ts) bind a generated artifact to its inputs; training-data source evidence (training-data-source-evidence.ts) records what a model was trained on for the rights report. - Watermark verification (
watermark-verification.ts) runs pluggableWatermarkDetectors — aMetadataTagDetectorand aC2paDetector— and resolves aWatermarkVerdictfromWatermarkSignalReports. This is an honest detector-driven seam: the verdict reflects what the detectors actually found, including "no watermark present," rather than asserting a watermark exists. - Synthetic-media labeling (
synthetic-media-labeling.ts) drives aLabelRequirement→LabelRenderCheck→LabelVerificationReportflow so the AI-content disclosure is provably rendered, and provenance badges (provenance-badges.ts) compose end-user-facingBadges (with aBadgeSeverityofinfo | caution | warning) "where they provide real value" — theProvenanceBadgeComposerdecides which badges to surface rather than blanket-labeling everything. - Content/model licensing review (
content-license-review.ts,model-license-review.ts) and the export surfaces — rights report (rights-report.ts), evidence export (evidence-export.ts), audit investigation export (audit-investigation-export.ts) — round out the source-lineage → rights-report → audit/privacy/compliance export chain the backlog enumerates.
These review/audit/provenance surfaces are exercised by the operator and admin consoles (see Admin Products — Web and Mobile and Tenant, Institution, and Operator Toolkit, whose audit-log explorer is backlog §20.4); the editorial release flow they gate is described in Collaboration, Review, and Templates.
Part 2 — Trust & Safety#
Trust & Safety (backlog §21) owns moderation, abuse, crisis, and appeals across
content, assistant behavior, persona/voice/avatar usage, generated media,
support contact, and educational integrity. Policies are taxonomized,
severity-classed, escalation-routed, audited, and evaluated. Everything below is
real code in @oshun/trust-safety; the parts that are runtime-owned (the actual
classifiers that emit a PolicyHit) are called out explicitly.
Policy taxonomy#
policy-taxonomy/categories.ts defines the canonical category enums. A
PolicyHit carries a discriminated-union PolicyCategory (family +
category), an optional subClass, a confidence in [0, 1], an
evidenceExcerpt, a detectorVersion, and a jurisdiction. The classifier
that produces a hit is the runtime's job; this module's job is to validate
it (validatePolicyHit) and map it to a deterministic enforcement action
(mapHitToAction).
Family (PolicyCategory.family) |
Real categories (*_CATEGORIES arrays) |
|---|---|
content |
hate, harassment, sexual-content, graphic-violence, self-harm, illegal.csam, illegal.terrorism, illegal.weapons, illegal.drugs, defamation, doxxing, electoral-disinformation, health-disinformation, scams, financial-exploitation |
assistant-behavior |
persona-drift, jailbreak, prompt-injection, deceptive-roleplay, off-policy-advice, harmful-instruction-generation, political-influence, unauthorized-memory-access |
synthetic-media |
deceptive-realism, identity-impersonation, nonconsented-likeness, deepfake, voice-clone-abuse, watermark-removal |
educational |
fabricated-citations, retracted-source-use, plagiarism, exam-integrity-violation, answer-key-leakage, standards-alignment-misrepresentation |
support-ops |
operator-harassment-of-customer, unauthorized-data-access, refund-abuse, social-engineering |
Sexual content carries a finer SEXUAL_NSFW_CLASSES subclass: suggestive,
explicit-adult-consensual, explicit-adult-nonconsensual, minor-sexual. The
validator enforces real cross-field invariants — a subclass may only attach to
sexual-content, and illegal.csam requires the minor-sexual subclass
(csam-requires-minor-subclass).
mapHitToAction is the deterministic enforcement core. It returns an
EnforcementAction — one of block, downgrade-visibility, warn-author,
route-for-human-review, or no-action — driven by curated key sets and the
hit's confidence:
- Always hard-block, regardless of confidence: the
minor-sexualandexplicit-adult-nonconsensualsubclasses, plus theHARD_BLOCK_KEYSset (content:illegal.csam,illegal.terrorism,illegal.weapons, the synthetic-media abusesnonconsented-likeness/voice-clone-abuse/deepfake/watermark-removal, and the support-opsunauthorized-data-access/social-engineering). - Jurisdiction-bound:
content:illegal.drugsonly hard-blocks when aJurisdictionPolicyOverlaydefines it in that jurisdiction; otherwise it routes for human review. An overlay can also elevate an otherwise soft-blocked category. - Confidence-gated: below
minConfidenceForHumanReviewthe action isno-action; jailbreak/prompt-injection block at or aboveminConfidenceForActionand route for review otherwise; soft-block and downgrade keys behave the same with their respective fallbacks. - Self-harm is special-cased to
downgrade-visibility(it flows through the crisis pathway rather than a blanket block — see below).
Why a separate map per key set rather than one severity score? Because
enforcement is not monotonic in confidence: a high-confidence scams hit
downgrades visibility while a low-confidence illegal.csam hit still
blocks. Encoding that as explicit category→action policy makes the behavior
auditable and testable rather than emergent from a threshold.
Severity classes and SLAs#
severity/severity.ts defines SEVERITY_CLASSES = ['P0', 'P1', 'P2', 'P3'] and
a machine-readable SlaBudget per class. The features prose describes the SLAs;
the actual enforcing shape — triageBudgetSeconds, actionBudgetSeconds,
requiresParallelIncident, requiresPostIncidentReview, weeklyAggregateOnly,
and minReviewerTier — is the real SLA_BY_SEVERITY constant:
| Severity | Triage budget | Action budget | Min reviewer tier | Parallel incident | Post-incident review | Weekly-aggregate only |
|---|---|---|---|---|---|---|
| P0 — imminent harm | 5 min (5 * 60) |
15 min (15 * 60) |
crisis-trained |
yes | yes | no |
| P1 — high severity / ongoing abuse | 30 min (30 * 60) |
2 h (2 * 3600) |
senior |
no | yes | no |
| P2 — moderate / low-confidence | 8 h (8 * 3600) |
48 h (48 * 3600) |
standard |
no | no | no |
| P3 — informational / pattern-only | weekly (7 * 86400) |
weekly (7 * 86400) |
standard |
no | no | yes |
classifySeverity is the deterministic classifier. The minReviewerTier is a
real gate — a P0 case may not be triaged by a standard reviewer — and
requiresParallelIncident / requiresPostIncidentReview are obligations the
runbook hangs off, not commentary.
Escalation is encoded, not narrated:
- The
minor-sexualandexplicit-adult-nonconsensualsubclasses are always P0 regardless of threat signals (the "non-consensual sexual imagery" / "child-protection signals" P0 classes). - A credible-threat triple —
hasNamedTarget && hasCrediblePlan && hasGeographicSpecificity— auto-escalates any hit to P0 (the "credible violence-to-others" class). - Base P0/P1 membership comes from
P0_CATEGORIES(content:illegal.csam,content:self-harm,synthetic-media:nonconsented-likeness) andP1_CATEGORIES(hate, harassment, identity-impersonation, voice-clone-abuse, deepfake, exam-integrity-violation). - P2 → P1 on repeat:
shouldEscalateP2OnRepeatescalates user-targeting harms (harassment/hate/doxxing/defamation, plus jailbreak/prompt-injection) whenpriorOccurrencesInLast30Days >= 1.
evaluateSla computes triage/action breach against the live timer, and there is
a separate AppealSlaBudget table (APPEAL_SLA_BY_SEVERITY) — appeals get
their own, slower budgets (P0 appeal: 30 min triage / 4 h second-review / 6 h
notify) because an appeal of a P0 decision is itself urgent but not the same
clock as the original imminent-harm response.
Decision classes and appeals#
decisions/decisions.ts taxonomizes decisions into appealable and
non-appealable sets:
APPEALABLE_DECISION_KINDS(8):content-removal,account-suspension-under-30-days,persona-suspension,comment-hiding,recommendation-suppression,voice-entitlement-suspension,avatar-entitlement-suspension,billing-action-reversal.NON_APPEALABLE_DECISION_KINDS(5):csam-removal,credible-threat-suspension,legal-hold-action,court-ordered-action,permanent-ban.
Each non-appealable kind carries a real operator runbook entry in
NON_APPEALABLE_RUNBOOK — mandatoryReportRequired, the
legalContactRoleRequired (trust-safety-legal | incident-response |
court-liaison), a retentionDays (CSAM and legal-hold at 365 * 7,
court-ordered at 365 * 10), and a summary. For example, csam-removal
requires a mandatory NCMEC/equivalent report, preservation under legal hold, and
two-reviewer signoff.
A SafetyDecision records kind, issuedByReviewerId, rationale,
severity, and a
twoReviewerSignoff: { secondReviewerId, atUnixSeconds } | null.
validateDecision enforces that two-reviewer signoff is present whenever it is
required — for P0, for the TWO_REVIEWER_DECISION_KINDS set
(csam-removal, credible-threat-suspension, court-ordered-action,
permanent-ban), for large accounts, public figures, decisions involving a
cloned voice or avatar, or decisions overriding Lilith policy — and that the
second reviewer is not the issuer (self-signoff).
The appeal lifecycle is a real state machine over APPEAL_STATES
(received → triaged → in-review → decided → notified → audited) with verdicts
uphold | overturn | partial:
fileAppealrefuses non-appealable decisions outright (decision-not-appealable) and stamps acooledOffUntilUnixSeconds.triageAppealenforces reviewer rotation — the triage reviewer may not be the original (reviewer-rotation-required) — and a cooling-off wait (cooling-off-not-elapsed).decideAppealenforces that the second reviewer is neither the original nor the triage reviewer, and requires a rationale.notifyAppealrecords thenotificationChannel(email|in-app|postal), andauditAppealbinds anauditTrailId.
This is why the appeal flow is trustworthy: a single reviewer can never carry an appeal end-to-end, and the state machine refuses to skip steps.
Crisis handling and the cross-surface crisis frame#
crisis/crisis.ts models detection, routing, region-aware resource delivery,
post-crisis check-in, and mandatory reporting. A CrisisDetection has a
CrisisDetectionSource (model-classifier, user-self-report,
third-party-report, pattern-match-across-sessions,
support-copilot-escalation) and a CrisisKind (suicidal-ideation,
self-harm-imminent, violence-to-others-credible, child-protection-signal,
domestic-violence-signal, medical-emergency).
routeCrisis assigns the dedicated crisis-trained-24x7 queue (bypassing
normal severity), and selects resources by region, then language, then
accessibility — it filters the catalog to the caller's region (or global),
prefers locale-matched resources (BCP-47 language-family aware), and ranks the
top five by accessibility-tag overlap then language specificity.
mandatoryReportRequired fires only for the child-protection-signal /
violence-to-others-credible kinds in the MANDATORY_REPORTING_REGIONS set
(US, CA, UK, AU, EU). createMandatoryReport resolves a per-region
LegalContact from the registry (e.g. NCMEC-class authorities), planCheckIn
schedules an opt-in follow-up and a noRecommendationCooldown, and
buildCrisisAuditRecord retains the event (7 years for child-protection
signals, 5 otherwise).
The standout piece is the cross-surface crisis-frame cascade
(crisis/crisis-frame-cascade.ts), the concrete implementation of a named exit
criterion. Activating a crisis frame for one surface previously did not
propagate; this module fixes that with a port-based publish/consume design:
- The event:
LILITH_CRISIS_FRAME_ACTIVATED_EVENT = 'lilith.crisis_frame.activated'— the exact topic string the architecture's sequence diagram names. - The surfaces:
CRISIS_FRAME_SURFACES = ['psyche', 'lilith-video', 'tara', 'iris', 'assistant']— the closed set every frame projects into. - Non-overridable directives: the payload
LilithCrisisFrameActivatedEventalways carrieshaltSynthesis: trueandsuspendMemoryWrites: true. A per-surface projector cannot soften them. - The flow:
activateLilithCrisisFramepublishes the event over an injectedCrisisFramePublishPort;consumeCrisisFrameActivationfans it out to each registeredCrisisFrameProjector, attempting each surface independently so one surface failing to enter its frame never blocks the others (every outcome —projected|skipped|failed— is recorded so a recovery sweep can re-project the failures).
Crucially, the crisis domain stays free of @oshun/event-bus — it depends
on ports only. The real Redis binding lives in crisis/crisis-frame-worker.ts:
createEventBusCrisisFramePublishPort(bus) adapts an IEventBus to the publish
port, and subscribeCrisisFrameWorker(bus, deps) subscribes a worker to
lilith.crisis_frame.activated and routes each event's payload through the
consumer fan-out, returning the Subscription so the caller can stop it. This
is the seam between the pure, testable cascade and the live message bus. The
per-surface behavior (Psyche halting synthesis, the assistant switching to a
crisis-aware persona) is documented in
Lilith Persona Policy and
Psyche Real-Time Runtime; the scene-level
mid-stream crisis frame is in
Scene Safety, Determinism, Provenance, and Cue Privacy.
Abuse-pattern detection#
abuse-patterns/abuse-patterns.ts covers five real detectors:
- Repeat-offender ladder:
REPEAT_OFFENDER_STAGES = ['warn', 'restrict', 'suspend', 'ban']withSTAGE_THRESHOLDS(warn: 1, restrict: 3, suspend: 5, ban: 8).applyOffensediscounts false-positive-rich categories (FP_RICH_CATEGORIES— health/electoral disinformation, off-policy advice) before escalating, so a noisy classifier does not over-punish. - Coordinated-abuse clustering:
detectCoordinationClustersbuckets by(promptFingerprint, targetEntityId), requires a minimum distinct-user count inside a time window, and scoresconfidencefrom user count, IP/device non-diversity (shared infrastructure raises suspicion), and tightness of the time window. - Bot/scripted signals:
classifyBotBehaviorflagsrapid-retry-after-refusal(≥5 in 5 min),prompt-permutation(≥10 in 5 min), and anytool-call-exfiltration-attempt. - Classifier drift:
detectClassifierDriftcompares baseline vs. recent false-positive/false-negative rates per(classifierId, domain)and emits aDriftAlertwhen the absolute delta exceeds the configured threshold. - Tenant-aggregate outliers:
classifyTenantAbuseRatescomputes a z-score per tenant against the platform mean and classifiesnormal | spike | anomaly(z ≥ 2 / z ≥ 3).
Operator surfaces#
operator-surfaces/operator-surfaces.ts builds the moderation cockpit:
buildAppealEvidencePackassembles the full context an appeal reviewer needs — original content,policyHits,classifierOutputs(id/score/version), prior incident and appeal counts, account context (age, tenant, roles), and persona context (persona id, tone-policy id) — plus the resolution rationale.buildRepeatOffenderTimelinemerges policy-hits, decisions, appeals, and crisis events into one reverse-chronological timeline with the consequence ladder applied.buildSafetyDashboardproduces aSafetyDashboardSnapshot: per-class volume, per-severity SLA attainment (triaged-in-budget / actioned-in-budget computed against the sameslaForbudgets), appeal outcomes, classifier health (healthy | degraded | failing), drift-alert counts, drift-cohort breakdowns, and crisis-event count.- Trend dashboards bucketize hits over time and slice them
trendByDomain/trendByTenant/trendByLocalefor weekly/monthly, per-domain, per-tenant, and cross-locale comparison.
Evaluation suites and release blocking#
evaluation/evaluation.ts makes "any safety eval regression blocks release" a
real gate. EVAL_CLASSES (content, contemplative, voice, avatar,
exam, crisis) each produce an EvalSuiteResult carrying
precision/recall/F1, per-locale and per-demographic-slice parity, and an
expectedCalibrationError. computeExpectedCalibrationError is a real
sample-weighted ECE over confidence bins — not a placeholder — so calibration
quality is measured, not asserted. Adversarial suites (prompt-injection,
jailbreak-template, cloned-voice-abuse, deepfake-generation, exam-cheat)
report a leakRate.
evaluateReleaseGate is the blocking function. It returns
{ allow: false, reasons } if a new build regresses F1, demographic-slice
parity, per-locale parity, calibration (ECE up), or adversarial leak rate beyond
the configured thresholds — or if isClassifierUpdate is true and the
championChallengerVerdict is not ready. Live evaluation closes the loop:
aggregateLiveSamples rolls operator-reviewed production samples into inferred
precision/recall, and updateGoldSet promotes operator-confirmed samples into
ground-truth gold-set rows for future scoring.
Real vs. runtime-owned — the honest boundary#
These cores are deterministic pure functions and state machines; the runtime owns enforcement. To be candid about where each side stands:
- Real and verified (deterministic cores): the full policy category enums and enforcement mapping, the severity/SLA budgets with reviewer-tier gates, the decision/appeal lifecycle with two-reviewer signoff and reviewer rotation, the crisis-frame cascade and its Redis-binding worker, the abuse-pattern detectors, the operator dashboards, the eval/release gate with a real ECE, and the review-package lifecycle and hash-chained audit/retention/attestation layer.
- Runtime-owned (honest seams, not stubs): the ML classifiers that emit
a
PolicyHitor aCrisisDetection(the cores validate and route what they are given); the durable append-only store behind the audit chain (the chain math is real; persistence is the platform's job); the real Redis bus the crisis worker binds (the cascade is bus-agnostic by design); and the live legal-contact registry / resource catalog thatrouteCrisisandcreateMandatoryReportare fed at runtime. - Adjacent domains, deliberately split: consent/memory and DSAR fan-out are
owned by
@oshun/privacyand Iris (@oshun/memory-iris) — see Privacy, Consent, Data Portability, and User Controls; immutable audit storage per the architecture is@oshun/audit-platform.
Note on a stale grounding reference.
libs/maat(@maat/compliance, with itsghana-data-protection-compliance-engine,regulatory-filing-automation-engine, andesg-reporting-engine) is a separate B2B intelligence product, not part of Oshun V1 governance. The implementation grounding for Oshun's review / T&S / privacy / billing logic is@oshun/review-persistence,@oshun/audit-platform,@oshun/trust-safety,@oshun/privacy, and@oshun/billing-support— do not readlibs/maatas the Oshun governance code.
Related#
- Privacy, Consent, Data Portability, and User Controls
— the consent taxonomy, DSAR state machine, residency routing, retention
constants, and regulatory-regime map (
@oshun/privacy); the privacy half of governance. - Support, Entitlements, Billing, and Customer Operations
— the support-case routing/SLA machine, entitlement classes, metered billing,
dunning, and the billing↔Aje entitlement bridge (
@oshun/billing-support). - Crypto Payments — Non-Custodial Entitlement Settlement — the settlement surface that drives subscription/entitlement state.
- Lilith Persona Policy — the persona policy substrate the crisis frame and assistant-behavior categories enforce against.
- Psyche Real-Time Runtime — the runtime that halts synthesis when a crisis frame is projected.
- Scene Safety, Determinism, Provenance, and Cue Privacy — the Living-Scenes governance spine the crisis frame composes onto.
- Collaboration, Review, and Templates — the editorial release flow the review-package lifecycle gates.
- Admin Products — Web and Mobile and Tenant, Institution, and Operator Toolkit — the consoles that surface review queues, the audit-log explorer (§20.4), and safety dashboards.
- Companion architecture page: Trust, Safety, and Privacy.
- The features hub: ../features.md.