{"ok":true,"checkedAt":"2026-06-02T19:12:31.243Z","profileVersion":"moral-trade-security-v0.3-2026-06","purpose":"Public security posture contract for Moral Trade headers, session boundaries, provider encryption assumptions, secret/key management, abuse throttling, and scale gates.","validation":{"status":"pass","validatorName":"moral-trade-security-profile","validatorVersion":"moral-trade-security-validator-v0.3","profileVersion":"moral-trade-security-v0.3-2026-06","checks":[{"id":"required-security-controls","label":"Security controls and honest status labels","status":"pass","evidence":"hsts_csp_headers, private_no_store_cache, supabase_auth_cookies, provider_encryption_at_rest, field_level_encryption_not_claimed, background_field_encryption_keyring, server_only_secret_management, two_factor_admin_gate, participant_session_review_revocation, contact_disclosure_mfa_step_up, device_session_review_gate, key_rotation_gate, platform_abuse_throttling, incident_response_reporting"},{"id":"browser-and-session-controls","label":"Browser headers, private cache, and Supabase session controls","status":"pass","evidence":"hsts_csp_headers:implemented, private_no_store_cache:implemented, supabase_auth_cookies:implemented"},{"id":"provider-boundary-and-nonclaims","label":"Provider encryption boundary and non-claims are explicit","status":"pass","evidence":"Moral Trade does not claim custom field-level encryption for every private Moral Trade table; background-networking sensitive text has a separate versioned keyring control. | Moral Trade does not claim the app-level MFA/2FA admin gate replaces provider-console MFA, device inventory, session revocation, or key-rotation evidence. | Moral Trade does not claim a completed key-rotation program until provider rotation records are published. | Moral Trade does not claim 24/7 staffed security operations or zero incidents; incident summaries stay aggregate and privacy-redacted. | Moral Trade does not claim zero security risk; public health endpoints expose blockers instead."},{"id":"admin-and-key-scale-gates","label":"MFA is enforced while device/session review and key rotation still gate sensitive scale","status":"pass","evidence":"two_factor_admin_gate:implemented, participant_session_review_revocation:implemented, contact_disclosure_mfa_step_up:implemented, device_session_review_gate:required_before_scale, key_rotation_gate:required_before_scale"},{"id":"incident-response-lane","label":"Incident response is published without overclaiming security completion","status":"pass","evidence":"implemented; Moral Trade does not claim custom field-level encryption for every private Moral Trade table; background-networking sensitive text has a separate versioned keyring control. | Moral Trade does not claim the app-level MFA/2FA admin gate replaces provider-console MFA, device inventory, session revocation, or key-rotation evidence. | Moral Trade does not claim a completed key-rotation program until provider rotation records are published. | Moral Trade does not claim 24/7 staffed security operations or zero incidents; incident summaries stay aggregate and privacy-redacted. | Moral Trade does not claim zero security risk; public health endpoints expose blockers instead."},{"id":"scale-gates","label":"Scale gates reference known controls","status":"pass","evidence":"sensitive_admin_scale->two_factor_admin_gate+device_session_review_gate+key_rotation_gate+incident_response_reporting, paid_action_volume_scale->platform_abuse_throttling+provider_encryption_at_rest+server_only_secret_management+key_rotation_gate+incident_response_reporting, trust_badge_scale->private_no_store_cache+supabase_auth_cookies+contact_disclosure_mfa_step_up+platform_abuse_throttling+incident_response_reporting"},{"id":"security-tests","label":"Security test hooks","status":"pass","evidence":"security_profile_validator, security_scale_gate_audit, security_implementation_source_smoke, no_overclaim_nonclaim_smoke, private_cache_header_smoke, security_profile_incident_lane_smoke, security_health_route_contract_smoke, technical_spec_security_smoke"}],"blockers":[]},"publicContract":{"controls":[{"key":"hsts_csp_headers","label":"HSTS, CSP, and browser security headers","status":"implemented","publicClaim":"Security headers are configured at the app edge; CSP is currently report-only.","evidence":"next.config.ts sets HSTS, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, and CSP report-only headers."},{"key":"private_no_store_cache","label":"Private no-store cache policy","status":"implemented","publicClaim":"Authenticated and sensitive routes, including private match rooms and saved-user surfaces, should not be cached as public pages.","evidence":"next.config.ts and background privacy controls mark dashboard, admin, agreement rooms, saved offers, MPGF account/admin, profile/job APIs, saved-search writes, and wish-registry search private no-store."},{"key":"supabase_auth_cookies","label":"Supabase auth cookies","status":"implemented","publicClaim":"Authentication is cookie-backed through Supabase.","evidence":"src/lib/supabase/proxy.ts and src/lib/supabase/server.ts refresh auth through server-side cookies."},{"key":"provider_encryption_at_rest","label":"Provider encryption at rest","status":"provider_boundary","publicClaim":"Encryption-at-rest is a provider-boundary control unless a field-level encryption control is explicitly published.","evidence":"Supabase, Vercel, Stripe, Every.org, and email providers are treated as processor/provider boundaries; Moral Trade does not claim custom field-level encryption for every table."},{"key":"field_level_encryption_not_claimed","label":"Platform-wide field-level encryption is not claimed","status":"not_claimed","publicClaim":"Provider encryption, RLS, redaction, cache, and consent controls still protect non-background private tables unless a table-specific field-encryption control is published.","evidence":"Background-networking sensitive text has a separate field-encryption control, but the public pilot does not claim app-level field encryption for every Moral Trade private table."},{"key":"background_field_encryption_keyring","label":"Background field-encryption keyring","status":"implemented","publicClaim":"Background-networking exact wishes, sensitive constraints, private source notes, connector consent notes, and deterministic synthesis summaries use app-level field encryption with versioned key ids and rotation support.","evidence":"src/lib/background-field-encryption.ts uses AES-256-GCM with versioned ciphertexts, active key ids from BACKGROUND_FIELD_ENCRYPTION_KEYS/BACKGROUND_FIELD_ENCRYPTION_ACTIVE_KEY_ID, legacy v1 decrypt candidates, and fail-closed saves when no key is configured."},{"key":"server_only_secret_management","label":"Server-only secret management","status":"implemented","publicClaim":"Secrets must stay in deployment/provider secret stores and never be copied into public docs or client bundles.","evidence":"API integrations use server-side environment variables and public contracts avoid publishing secret values."},{"key":"two_factor_admin_gate","label":"2FA/MFA admin gate","status":"implemented","publicClaim":"Operator consoles and review mutations require an allowlisted admin account with an active authenticator MFA session.","evidence":"src/lib/admin.ts requires an allowlisted admin email plus an active Supabase authenticator MFA session (AAL2) before admin queues or review actions can run; app admin pages, MPGF admin actions, background data-right review, and core review mutations call that gate."},{"key":"participant_session_review_revocation","label":"Participant session review and revocation","status":"implemented","publicClaim":"Participants can inspect the current background-networking session window and revoke other active Supabase sessions from the dashboard.","evidence":"src/lib/background-account-security.ts reads current Supabase JWT session_id/iat/exp/aal claims, the dashboard account-security panel shows a redacted current-session review, and src/app/background-networking/actions.ts exposes Supabase signOut({ scope: \"others\" }) to revoke other active sessions."},{"key":"contact_disclosure_mfa_step_up","label":"Contact disclosure MFA step-up","status":"implemented","publicClaim":"Contact-level introductions require an explicit disclosure stage and MFA step-up before contact details can be released.","evidence":"src/lib/background-disclosure.ts requires contact-level grants or contact_email field disclosure to pass requiresContactDisclosureStepUp; src/lib/background-disclosure.test.ts covers the contact disclosure step-up boundary."},{"key":"device_session_review_gate","label":"Device/session review gate","status":"required_before_scale","publicClaim":"Sensitive admin scale requires provider-level device inventory and anomalous-session review evidence in addition to participant session revocation.","evidence":"Participant current-session review and other-session revocation are implemented, but the public pilot does not yet publish provider-wide device inventory, anomalous-session alerting, or completed operator session-review evidence."},{"key":"key_rotation_gate","label":"Key rotation gate","status":"required_before_scale","publicClaim":"Paid-action or trust-badge scale requires provider secret/key rotation records and rollback notes; background field encryption exposes its own versioned keyring boundary.","evidence":"Background field encryption now supports versioned active key ids, but the public pilot does not yet publish provider-wide rotation cadence, rollback evidence, or completed rotation records for every provider secret."},{"key":"platform_abuse_throttling","label":"Platform abuse throttling","status":"implemented","publicClaim":"Abuse-prone surfaces are rate-limited and must fail safely.","evidence":"Core signup, login, offer creation, comments, privacy requests, public contract reads, private advisory evaluations, wish search, profile portability, and analytics ingest have named rate-limit surfaces."},{"key":"incident_response_reporting","label":"Incident response reporting","status":"implemented","publicClaim":"Incident intake, response phases, public aggregate disclosure rules, and non-claims are validator-backed; this does not complete MFA, key rotation, device/session review, or field-level encryption.","evidence":"config/moral-trade/incident-response-profile.json and /api/moral-trade/incident-response/health publish intake, severity, disclosure, response-phase, and readiness-gate checks."}],"scaleGates":[{"key":"sensitive_admin_scale","label":"Sensitive admin scale","requires":["two_factor_admin_gate","device_session_review_gate","key_rotation_gate","incident_response_reporting"],"rule":"Do not expand sensitive admin access until MFA, device/session review, key rotation, and incident-response evidence are ready.","readiness":{"status":"blocked","gateKey":"sensitive_admin_scale","requiredControls":["two_factor_admin_gate","device_session_review_gate","key_rotation_gate","incident_response_reporting"],"blockers":["scale_control_not_ready:device_session_review_gate","scale_control_not_ready:key_rotation_gate"]}},{"key":"paid_action_volume_scale","label":"Paid-action volume scale","requires":["platform_abuse_throttling","provider_encryption_at_rest","server_only_secret_management","key_rotation_gate","incident_response_reporting"],"rule":"Do not expand paid-action volume until provider/security boundaries, key rotation, incident response, and abuse throttles are documented.","readiness":{"status":"blocked","gateKey":"paid_action_volume_scale","requiredControls":["platform_abuse_throttling","provider_encryption_at_rest","server_only_secret_management","key_rotation_gate","incident_response_reporting"],"blockers":["scale_control_not_ready:key_rotation_gate"]}},{"key":"trust_badge_scale","label":"Trust badge scale","requires":["private_no_store_cache","supabase_auth_cookies","contact_disclosure_mfa_step_up","platform_abuse_throttling","incident_response_reporting"],"rule":"Do not expand public trust badges unless private cache, authenticated session, abuse throttling, and incident reporting remain verifiable.","readiness":{"status":"pass","gateKey":"trust_badge_scale","requiredControls":["private_no_store_cache","supabase_auth_cookies","contact_disclosure_mfa_step_up","platform_abuse_throttling","incident_response_reporting"],"blockers":[]}}],"publicNonClaims":["Moral Trade does not claim custom field-level encryption for every private Moral Trade table; background-networking sensitive text has a separate versioned keyring control.","Moral Trade does not claim the app-level MFA/2FA admin gate replaces provider-console MFA, device inventory, session revocation, or key-rotation evidence.","Moral Trade does not claim a completed key-rotation program until provider rotation records are published.","Moral Trade does not claim 24/7 staffed security operations or zero incidents; incident summaries stay aggregate and privacy-redacted.","Moral Trade does not claim zero security risk; public health endpoints expose blockers instead."],"securityTests":["security_profile_validator","security_scale_gate_audit","security_implementation_source_smoke","no_overclaim_nonclaim_smoke","private_cache_header_smoke","security_profile_incident_lane_smoke","security_health_route_contract_smoke","technical_spec_security_smoke"]},"blockers":[]}