Commit Graph

80 Commits

Author SHA1 Message Date
maaz519 611ca74cea feat(iios): DSR right-to-erasure (redact-in-place) + compliance hold (P9)
Adds IiosComplianceHold + IiosSourceHandle.redactedAt and a DsrService whose
eraseSubject redacts the caller's PII in place (message bodies, identity
display, raw payloads, support/inbox/transcript text) while preserving
externalId (source preservation), structure, and the audit trail. An active
compliance hold blocks erasure until released; every op is audited and
tenant-fenced. Erasure is idempotent (KG-03).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 03:24:43 +05:30
maaz519 67da42a103 feat(iios): projection-cursor observability on /metrics + smoke (P9)
Adds a global `projections` section to GET /metrics exposing each cursor's
position (last_event_id/last_offset), determinism checksum, and lagMs.
smoke-projection.mjs injects events and asserts the projection's ordered
high-water-mark advances with a 64-hex rolling checksum (KG-06).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:48:14 +05:30
maaz519 2424739e3a feat(iios): projectors checkpoint the projection cursor (P9)
All 5 projectors (route/ai/inbox/calendar/raw-event) now advance their
IiosProjectionCursor after a freshly-claimed event is applied — split into
claim → apply → advance so a duplicate never double-counts and a throw leaves
the cursor untouched (event replays via the DLQ). Inbox's two topics get two
cursor rows. Proves KG-06 replay reproduction at the projection level.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:44:23 +05:30
maaz519 1997fe48bb feat(iios): projection-cursor ledger + ProjectionCursorService (P9)
Adds the doc-mandated IiosProjectionCursor (ordered high-water-mark +
rolling checksum per projection/topic/partition) and a reusable
ProjectionCursorService.advance(). The checksum is a deterministic fold over
the ordered event stream, so replaying the same events reproduces it — the
KG-06 proof that replay reproduces projection outcomes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:39:31 +05:30
maaz519 cdb399a9c1 feat(iios): idempotency smoke + P9 slice-6 verification
smoke-idempotency.mjs: dup POST /v1/support/tickets with the same
Idempotency-Key replays the same ticket, same key + different body → 409,
and a second tenant reusing the key gets its own ticket (isolation).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:27:20 +05:30
maaz519 093f6484b4 feat(iios): idempotent support ticket + callback creates via ledger (P9)
SupportService.createTicket + requestCallback now accept an optional
idempotencyKey (from the Idempotency-Key header). With a key, a same-body
retry replays the same row and a different-body reuse is a 409; without one,
they run unwrapped as before. Tenant-scoped via the command ledger.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:22:19 +05:30
maaz519 b8b7e0d3e8 feat(iios): idempotency-command ledger + IdempotencyService (P9)
Adds the doc-mandated IiosIdempotencyCommand table + a reusable
IdempotencyService.run() that writes IN_FLIGHT at command start, replays the
cached response on a same-key/same-body retry, rejects a same-key/different-body
reuse (409), and retries a FAILED command. Tenant-scoped via
@@unique([scopeId, commandName, idempotencyKey]) (KG-02/KG-06).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:19:03 +05:30
maaz519 dbf8f814c0 feat(iios): tenant-scoped /v1/dlq REST + chaos endpoint + smoke (P9 slice 5)
GET /v1/dlq lists the caller tenant's dead-letters; POST /v1/dlq/:id/replay
fences by assertOwns (KG-02) + audits each replay. Dev-only POST
/v1/dev/chaos/poison + ChaosConsumer (fails first delivery, succeeds on
replay) drive smoke-dlq.mjs: poison → QUARANTINED → cross-tenant denied →
owner replay → RESOLVED. Adds dev.chaos.v1 contract event.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 02:01:40 +05:30
maaz519 d3d557766e feat(iios): wire projectors + relay into DLQ (P9 chaos-safe)
Projectors register a replay handler and route bus errors to
dlq.onConsumerFailure (dead-letter + clear the claim-then-fail claim)
instead of swallowing them. Relay dead-letters an outbox event after
IIOS_OUTBOX_MAX_ATTEMPTS instead of retrying forever. Chaos test proves
poison → DLQ → replay resolves while sibling events keep flowing (KG-13/KG-06).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 01:43:57 +05:30
maaz519 208fb0b4f0 feat(p9): IiosDlqItem + DlqService (dead-letter + deterministic replay)
Task D.1: mandated dlq_item table (sourceType/sourceId/failureStage/errorCode/
retryCount/payloadRef/consumerName/scopeId/status). DlqService.record (idempotent
per consumer+sourceId, bumps retryCount), onConsumerFailure (quarantine + clear the
IiosProcessedEvent claim so it's replayable — fixes claim-then-fail), registerHandler
+ replay (clears claim, awaits the registered consumer handler → RESOLVED on success,
QUARANTINED+retry on repeat throw; outbox-sourced items reset to PENDING). Wired into
OutboxModule; resetDb truncates it. 3 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 01:28:48 +05:30
maaz519 e5d3ce5ecd feat(p9): tenant-scoped /metrics + observability smoke; slice-4 verification green
Task O.4: GET /metrics (session-auth) returns the caller tenant's counters
(interactions by kind/status, outbound by status, AI jobs + cost, tickets,
meetings, inbox, audit-link count) via findScope + Prisma groupBy — no cross-tenant
totals — plus a global relay-lag section. smoke-observability proves the mandated
gate end to end: x-trace-id response header, event correlationId == request trace,
audit link in DB, /metrics counters. Slice-4 verification: 122 tests green, builds,
boundary clean, observability smoke + all prior smokes pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 01:14:20 +05:30
maaz519 6548b40f17 feat(p9): iios_audit_link table + audit binding at decision points
Task O.3: IiosAuditLink (traceId/correlationId/scopeId/actorRefId/action/
resourceType/resourceId) + recordAudit() helper (reads the current trace from ALS,
best-effort). Written at the decision/mutation points — route approve/deny, AI
accept/reject, meeting summarize, outbound send — so the trace appears in DB and a
decision can be replayed / traced across services (mandated iios_audit_link).
Migration audit-link; resetDb truncates it. 2 tests bind approve/accept to a trace.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 01:08:55 +05:30
maaz519 1d3e18f417 feat(p9): propagate trace id into emitted events + structured relay/gateway logs
Task O.2: ai/calendar/route/ingest emit sites now stamp traceparent + insignia.
correlationId from interaction.traceId ?? currentTraceId() ?? generated (mirroring
message.send; inbox/inbound already carried correlationId). toTraceparent is hex-safe
(UUID used as-is, other ids hashed). OutboxRelay logs a structured relay.publish per
event (eventType/aggregateId/correlationId); MessageGateway logs ws.deliver. Tests:
an event's correlationId equals the active request trace, with a generated fallback.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 01:04:24 +05:30
maaz519 0f923303d3 feat(p9): request-scoped trace context + middleware + structured logger
Task O.1: AsyncLocalStorage trace context (currentTraceId/runWithTrace/toTraceparent)
read by singleton services with no DI churn; Express traceMiddleware derives a trace
id per request (x-trace-id → traceparent → generated), echoes x-trace-id on the
response, runs the request in-context, and logs a structured http.request line on
finish. Minimal JSON structured logger stamps traceId on every line. Wired via
app.use in main.ts. 4 tests: scope, concurrency isolation, traceparent shape/parse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 00:50:15 +05:30
maaz519 09dce7fdb4 docs: OpenAPI 3.0 spec (openapi.yaml) for the IIOS API
Machine-readable spec covering all ~44 endpoints across health/dev/interactions/
threads/inbox/support/adapters/routes/ai/calendar with request/response schemas,
bearer auth, tenant/consent error codes (400/401/403/404), and reusable enum +
DTO components. Validated with @redocly/cli (valid OpenAPI 3.0). Importable into
Swagger UI / Postman / Insomnia.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 22:29:02 +05:30
maaz519 269bdab589 docs: API & SDK guide for QA and developers
Full as-built reference: run/auth (dev tokens), conventions (idempotency, tenancy,
error codes), every REST endpoint across health/dev/interactions/threads/inbox/
support/adapters/routes/ai/calendar with request/response shapes, the kernel-client
+ 6 React hook SDKs, a curl QA quickstart + the 8 smoke scripts, env var reference,
and enum vocabularies.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 22:04:33 +05:30
maaz519 ed53decd3e feat(p9): tenant isolation smoke + slice-3 verification green
Task T3.5: smoke-tenant.mjs — two dev tokens (org_A/org_B); tenant B reading A's
meeting → 403 (KG-02), B's list excludes A's, A reads its own → 200. Slice-3
verification: 114 tests green, pnpm -r build all packages, boundary clean, tenant
smoke + capability smoke + all prior smokes (realtime/inbox/support/adapter/route/
ai/calendar) pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:59:51 +05:30
maaz519 e7b8845c8a feat(p9): per-tenant outbound quota + cellId assignment
Task T3.4: OutboundService gains a per-tenant egress cap (tenantLimit/tenantWindowMs,
IIOS_TENANT_OUTBOUND_*) counting a scope's commands in the window — a noisy tenant
is RATE_LIMITED while others keep sending (noisy-neighbor protection). Persists
scopeId on every command (fixes the previously-unscoped table). resolveScope assigns
IiosScope.cellId (IIOS_CELL_ID, default cell-default) — the cell-partition hook.
Tests: per-tenant cap isolates tenants; new scopes carry a cellId.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:55:14 +05:30
maaz519 d002c8f521 test(p9): cross-tenant isolation suite (KG-10)
Task T3.3: isolation.spec.ts — two tenants (org_A/org_B) on the same app. Proves
tenant B is denied on approve/getArtifact/accept/getMeeting/summarize of A's
resources, B's lists (decisions/artifacts/meetings) show none of A's, the denied
calls neither mutate A's data nor create a scope for B, and each tenant sees only
its own lists. The mandated one-DB tenant-isolation test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:53:03 +05:30
maaz519 ed0d4dae80 feat(p9): fence AI + calendar + message by-id leaks (tenant scope)
Task T3.2: AiJobService.getArtifact/accept/reject assertOwns on artifact.job.scopeId;
listArtifacts scoped to caller. CalendarService.getMeeting/setConsent/generateTranscript/
summarize/listActionItems assertOwns on meeting.scopeId (optional principal → asserts
when supplied by a controller, skipped for internal calls). MessageService.getMessageById
gains the same optional fence. Controllers thread the principal through. All 46
ai/calendar/routing/messaging tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:51:10 +05:30
maaz519 063049b724 feat(p9): scope-ownership assert + fence routing approve/deny/listDecisions
Task T3.1: ActorResolver gains findScope (no-create) + assertOwns(principal,
resourceScopeId) → ForbiddenException on mismatch (KG-02). RouteService.approve/
deny now assertOwns on the decision's binding scope before mutating; listDecisions
is scoped to the caller. Fixes the critical cross-tenant mutation (tenant A could
approve tenant B's route). Also adds IiosScope.cellId + IiosOutboundCommand.scopeId
columns (migration tenant-isolation) + cell assignment on scope create. Test:
another tenant approving → Forbidden, decision unchanged, no scope created, empty list.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:46:40 +05:30
maaz519 27103529e6 feat(p9): consent-at-egress smoke + slice-2 verification green
Task S2.3: capability smoke asserts the CMP consent gate is consulted at egress
(NOT_REQUIRED → send proceeds); the DENY→BLOCKED and ALLOW→receipt paths are
unit-covered. Slice-2 verification: 110 tests green, pnpm -r build all packages,
boundary clean, capability smoke PASS, all prior smokes (realtime/inbox/support/
adapter/route/ai/calendar) still pass through the consent-gated broker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:33:51 +05:30
maaz519 cdc59be481 feat(p9): thread purpose + persist consent receipt through OutboundService
Task S2.2: OutboundService.send gains an optional purpose, passes it to the broker,
and persists the returned consentReceiptRef on IiosOutboundCommand (new nullable
column, migration outbound-consent). RouteService.execute passes 'route_forward';
calendar reminders pass 'meeting_reminder'. CMP-DENY → command BLOCKED, no send.
2 tests: receipt recorded on allow, purpose-DENY blocks.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:26:01 +05:30
maaz519 2223d7a891 feat(p9): CMP consent gate in the Capability Broker
Task S2.1: the broker now checks consent (cmp.checkPurpose) after the OPA gate +
obligations and before the provider — a DENY blocks the send (BLOCKED/CONSENT_DENIED,
provider never called); ALLOW/NOT_REQUIRED proceed, ALLOW carrying the consent
receipt. Contracts gain CapabilityRequest.purpose + CapabilityResult.consentReceiptRef.
FakeCmp is now purpose-aware (denyPurpose/allowOnly). 5 new tests: allow+receipt,
deny→blocked, not-required, purpose-aware, OPA-before-CMP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 21:23:49 +05:30
maaz519 f7519d36f0 feat(p9): real-egress proof (env-gated HttpProvider) + /health bindings + smoke
Task 9.5: /health now reports the egress provider backing each channel (sandbox
vs http). scripts/smoke-capability.mjs proves the slice end to end: sandbox egress
SENT through the broker; EMAIL routed to the env-gated HttpProvider and actually
delivered to a LOCAL echo server (real egress, no external network, no credentials);
idempotent replay; /health bindings. App wires CapabilityModule.

P9 slice-1 verification: 103 tests green, pnpm -r build all packages+demos,
boundary clean, capability smoke PASS, all prior smokes (realtime/inbox/support/
adapter/route/ai/calendar) still PASS through the broker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:38:47 +05:30
maaz519 a1f46646ee feat(p9): adapter certification checklist (certifyProvider)
Task 9.4: certifyProvider runs the P9 conformance checklist a provider must pass
before backing a channel — declares explicit capabilities, returns providerRef +
recognized outcome (never throws), repeatable/idempotent, tolerates empty payload.
2 tests: SandboxProvider passes; a throwing/no-capability provider fails with the
specific failing checks listed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:05:04 +05:30
maaz519 28e517fc1b feat(p9): route OutboundService through the Capability Broker
Task 9.3: OutboundService now delegates the execute step to CapabilityBroker
(policy-gated + obligation-enforced) instead of calling a provider directly, while
keeping idempotency + rate-limit + the command/attempt ledger. BLOCKED obligations
→ command BLOCKED; a fail-closed throw marks the command FAILED then propagates.
AdaptersModule imports CapabilityModule; P4/P6/P8 egress now flows through the
broker unchanged. Updated 6 spec constructions; added a DENY_OUTBOUND test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 20:04:11 +05:30
maaz519 c50a501f32 feat(p9): Capability Broker — governed egress + fail-closed gate + obligations
Tasks 9.1+9.2: contracts (CapabilityRequest/Result/Provider, PolicyObligation) +
service CapabilityBroker that fails closed via opa (PolicyDeniedError, nothing sent),
enforces obligations before any provider call (DENY_OUTBOUND/REVIEW → BLOCKED;
MASK/REDACT → mask payload field), then routes to a CapabilityProviderRegistry
(SandboxProvider default; env-gated HttpProvider overrides per channel; unknown
channel fails closed). 5 tests: allow/deny/block/redact/unknown-channel.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 19:58:25 +05:30
maaz519 e11964b8bc feat(p8): meeting-studio demo + smoke-calendar; P8 verification green
Task 8.7: apps/meeting-studio (Vite, port 5178) — schedule a meeting, invite
attendees, toggle per-attendee recording consent, generate transcript (BLOCKED
until unanimous consent — KG-14), summarize, see AI summary + action-item inbox.
scripts/smoke-calendar.mjs proves the P8 guarantees end to end: direct schedule,
consent gate BLOCKED→READY (KG-14), summary linked to a P7 ai_artifact, action
items, attendee-visibility exclusion (Scenario 6), meeting_request genesis,
simulated provider sync (idempotent).

P8 verification: 95 tests green, pnpm -r build all packages+demos, boundary
passes and fails on meeting-web->service, smoke-calendar PASS, prior smokes
(realtime/inbox/support/adapter/route/ai) PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 18:22:24 +05:30
maaz519 ca9498ce83 feat(p8): /v1/calendar REST + kernel-client methods + @insignia/iios-meeting-web
Task 8.6: CalendarController exposes schedule/request(+fromCallback/fromClaim)/
list/get/consent/transcript/summarize/action-items/providers(+sync) (session-auth).
kernel-client RestClient gains scheduleMeeting/requestMeeting/listMeetings/
getMeeting/setConsent/generateTranscript/summarizeMeeting/listActionItems/
connect+syncCalendarProvider + Meeting/MeetingParticipant/MeetingActionItem types.
New @insignia/iios-meeting-web (MeetingProvider + useMeetings/useMeeting/useSchedule/
useConsent/useSummarize/useActionItems). Boundary: meeting-web -> contracts +
kernel-client (fails on meeting-web->service).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 18:09:18 +05:30
maaz519 83369f2055 feat(p8): simulated calendar adapter (provider · sync cursor · availability)
Task 8.5: CalendarAdapter connects a SIMULATED provider account + sync cursor,
deterministically pulls stable external events (idempotent by externalEventId,
advancing the cursor), records availability windows, and computes free/busy from
overlapping calendar events. No network. Real provider via Capability Broker = P9.
3 tests: connect, sync idempotent + cursor advance, availability busy/free.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 18:02:27 +05:30
maaz519 2ec427cecc feat(p8): reminders (sandbox + inbox) + CalendarProjector (AI-event auto-bridge)
Task 8.4: schedule queues one sandbox reminder (OutboundService) + a SYSTEM_ALERT
inbox item per participant, idempotent (outbound key + per-meeting marker) +
meetingReminderQueued event. CalendarProjector consumes aiArtifactAccepted → for
each EVENT claim proposes a meeting_request (PROPOSED, sourceClaimId), idempotent
via claim() + per-claim dedup. 2 tests: reminder replay-safe, AI-event→request once.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 18:00:53 +05:30
maaz519 55acc3c187 feat(p8): consent gate → transcript → summary → action items (KG-14/Scenario 6)
Task 8.3: checkMeetingConsent requires unanimous attendee GRANTED consent + CMP
non-DENY before any recording artifact. generateTranscript → BLOCKED (no segments)
unless the gate passes, else READY + speaker segments. summarize re-checks consent
live (revoke blocks re-summary), reuses P7 AiJobService over a synthetic transcript
interaction → IiosMeetingSummary(aiArtifactId) + action items + per-attendee
MEETING_FOLLOWUP inbox items, excluding visibility=NONE. 6 tests cover the spine.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:57:36 +05:30
maaz519 6edb0cc0cc feat(p8): CalendarService — 3 genesis paths converge on schedule
Task 8.2: requestMeeting + fromCallback (bridge) + fromEventClaim (accepted P7
AI EVENT claim, human-confirmed) + direct scheduleDirect. schedule() fails closed
via opa, creates meeting + organizer/attendee participants + calendar_event,
closes the request, and populates IiosCallbackRequest.meetingRef when bridged.
5 tests: direct/callback/AI genesis, un-accepted claim refused, opa-deny fail-closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:54:03 +05:30
maaz519 21772e7611 feat(p8): calendar/meeting schema + enums + events + migration
Task 8.1: 12 Calendar/Meeting tables (meeting_request, meeting, participant,
transcript, segment, summary, generic action_item + meeting link, provider
account, calendar_event, availability_window, sync_cursor) + 13 enums; migration
calendar-init. Adds calendar.meeting.requested/scheduled/reminder.queued/
summarized events. resetDb truncates the new tables. Kernel already had the
MEETING_REQUEST / MEETING_FOLLOWUP / callback.meetingRef stubs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 17:51:35 +05:30
maaz519 37f8ceeaf3 feat(p7): ai-studio demo + smoke-ai; P7 verification green
Task 7.6: apps/ai-studio (Vite, port 5177) — ingest a message, run CLASSIFY/
SUMMARIZE/EXTRACT, see proposal cards with confidence, evidence citations,
abstention, model/cost + a budget meter, and accept/reject; built on the ai-web
SDK via AiProvider. scripts/smoke-ai.mjs proves the P7 guarantees end to end:
auto-CLASSIFY → AI flag → routing REVIEW/DENY never ALLOW (KG-05), summary cites
evidence, EXTRACT stays DISCUSSION (Scenario 7), replay-once, accept.

P7 verification: 79 tests green (3x stable), pnpm -r build all packages+demos,
boundary passes and fails on ai-web->service, smoke-ai PASS, prior smokes
(realtime/inbox/support/adapter/route) PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:53:40 +05:30
maaz519 881b37afd0 feat(p7): /v1/ai REST + kernel-client AI methods + @insignia/iios-ai-web SDK
Task 7.5: AiController exposes POST /v1/ai/jobs, GET /v1/ai/artifacts(+/:id),
POST accept/reject (session-auth). kernel-client RestClient gains runAiJob/
listArtifacts/getArtifact/acceptArtifact/rejectArtifact + AiArtifact/AiClaim/
AiEvidenceLink/AiModelRun types. New @insignia/iios-ai-web (AiProvider, useRunJob,
useAiProposals, useArtifact). Boundary allowlist: ai-web -> contracts +
kernel-client (fails on ai-web->service).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:42:07 +05:30
maaz519 68d922c248 feat(p7): wire AI into P6 routing + AiProjector (KG-05 structural proof)
Task 7.4: route-simulator now unions RULE flags with persisted AI moderation
flags before decide() — so AI flags influence routing exactly like rule flags,
only ever REVIEW/DENY, never ALLOW. SUMMARY/TRANSCRIPT/DIGEST previews render a
proposed AI summary (aiSourced flag) instead of the P6 stub, still preview-only.
AiProjector auto-runs CLASSIFY on interaction.normalized (channel-bearing only),
idempotent via claim(). 4 tests prove KG-05: AI flag forces REVIEW on an
auto-ALLOW binding, DENY on CHILD, AI summary in preview with 0 sends, projector
idempotency. Full suite 79 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:38:00 +05:30
maaz519 c6dc1cf112 feat(p7): AiJobService + AiBudgetGuard + local inference (gate→budget→propose)
Task 7.3: AiJobService runs scoped/purposed AI jobs that only propose — fails
closed via OPA (KG-03), degrades on budget (AiBudgetGuard sums costUnits, KG-12),
then persists job+modelRun+artifact(PROPOSED)+claims+evidence with full
provenance. CLASSIFY also proposes IiosModerationFlag(proposedBy:'AI'). accept/
reject record human feedback + emit events. Idempotent per job key. INFERENCE_PORT
binds LocalDeterministicInference for nest start; specs inject testkit FakeInference.
8 tests: classify/summarize/extract, fail-closed, budget-degrade, idempotent, accept.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:34:32 +05:30
maaz519 e03f2f72e4 feat(p7): FakeInference deterministic provider + golden eval registry
Task 7.2: FakeInference implements the InferencePort with keyword vocabulary
mirroring the P6 RuleEngine; deterministic (no clock/random) so AI artifacts are
replayable. Golden fixtures (AI_GOLDEN) + inference.spec.ts assert byte-identical
replay, abstention, and Scenario-7 (EVENT never exceeds DISCUSSION certainty).
Controls: abstain()/deny()/setCost().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:29:51 +05:30
maaz519 42bb99c09f feat(p7): AI tables + enums + migration + events + InferencePort contract
Task 7.1: 7 AI-proposal-layer tables (IiosAiJob, IiosAiModelRun, IiosAiArtifact,
IiosAiClaim, IiosAiEvidenceLink, IiosAiToolCall, IiosEmbeddingRef) + enums;
migration ai-init. Adds ai.job.created / ai.artifact.proposed / ai.artifact.accepted
events and a standalone InferencePort contract (not part of sealed IiosPlatformPorts).
resetDb truncates the new tables.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 16:26:21 +05:30
maaz519 54c47dd133 feat(p6): route-admin demo + route smoke; P6 verification green
Task 6.6: apps/route-admin (Vite, port 5176) — create bindings, simulate a
message (preview-first, no send), see color-coded per-destination decisions
with reason codes + preview, approve/deny REVIEW rows; built on the
community-web SDK via CommunityProvider.

scripts/smoke-route.mjs: 3 MANUAL bindings → 'party at 9 PM' → children(CHILD)
DENY / adults+seniors REVIEW / 0 sends on simulate; approve → exactly one
sandbox forward; AUTOMATIC safe binding auto-forwards via RouteProjector.

P6 verification: 63 tests green, pnpm -r build all packages+demos, boundary
passes and fails on community-web→service, route smoke PASS, prior smokes
(realtime/inbox/support/adapter) PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 15:33:42 +05:30
maaz519 1ee737c025 feat(p6): kernel-client route methods + @insignia/iios-community-web SDK
Task 6.5: add createBinding/listBindings/simulateRoute/listRouteDecisions/
approveDecision/denyDecision to RestClient + RouteBinding/RouteDecision types.
New @insignia/iios-community-web package (CommunityProvider, useBindings,
useRoutePreview, useRouteDecisions). Boundary allowlist: community-web ->
contracts + kernel-client.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 15:12:50 +05:30
maaz519 095ea869aa feat(service): P6.4 RouteProjector — AUTOMATIC forwarding on interaction.normalized
Reacts to channel-bearing (ingested/adapter) interactions, not native DMs;
simulates per binding; AUTOMATIC+ALLOW executes to sandbox, MANUAL/REVIEW/DENY
stay pending; idempotent. 8 route tests; 63 total.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:43:24 +05:30
maaz519 968a90bdb9 feat(service): P6.3 route REST + approve/deny → execute to sandbox
RouteService (createBinding/listBindings/simulate/listDecisions/approve/deny/
execute/flushDigest); approve REVIEW→ALLOW + route.approved event → execute via
P5 OutboundService (sandbox, idempotent per decision); deny never executes.
7 route endpoints; PORTAL adapter registered. 5 route tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:40:08 +05:30
maaz519 7ed3c11891 feat(service): P6.2 RuleEngine + RouteSimulator (deterministic, preview-first)
Keyword moderation flags; deny-by-default for protected (CHILD) destinations,
REVIEW for other flags/requiresReview, ALLOW otherwise; versioned rulepack for
replay. Simulate renders per-format previews + persists decisions, NEVER sends.
BDD (party@9pm → children DENY / adult+seniors REVIEW / 0 sends) + replay green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:29:01 +05:30
maaz519 dfd87cdde7 feat(service): P6.1 route tables (route_binding, route_decision, moderation_flag) + enums + events
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:24:53 +05:30
maaz519 b879c9eba2 feat: P5.5 dev inject + adapter-inspector demo + adapter smoke (P5 complete)
Dev-only POST /v1/dev/webhook/:type signs+injects a sample payload. apps/adapter-
inspector (Vite): inbound raw events + outbound commands/attempts, simulate-inbound
+ test-send buttons. smoke-adapter proves signed->normalized->interaction, bad-sig
401, sandboxed outbound (no network). 55 tests; all 4 smokes pass; boundary enforced.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:54:18 +05:30
maaz519 4f661f4c81 feat(service): P5.4 outbound sandbox sink + rate limit + inspector read endpoints
OutboundService: idempotent commands, per-(channelType,target) rate-limit bucket,
sandbox send (no network) + delivery attempts. POST /v1/adapters/:type/send +
GET inbound/outbound (session-auth). 55 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:46:56 +05:30
maaz519 29b64c3c4e feat(service): P5.3 inbound adapter pipeline (ACK-fast webhook + RawEventProjector) + traceId
POST /v1/adapters/:type/webhook verifies HMAC (fail-closed) -> stores raw ->
emits raw.received -> 202. RawEventProjector consumes it off the relay, normalizes
via the adapter, reuses IngestService (traceId threaded raw->interaction).
Deduped on (channelType, externalEventId). rawBody enabled. 48 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 13:44:23 +05:30