Rift is the ideal dogfood app for Squid Mesh because it exercises the runtime through real human-operated workflows, not artificial examples.
It stress tests:
- Human-in-the-loop approval and rejection paths.
- Cancellation and terminal-state behavior.
- Durable side effects after approval, rejection, cancellation, assignment, and submission.
- Runtime inspection through linked SquidSonar views.
- Audit history and user-facing timelines.
- Failure handling when workflow execution succeeds but host-defined side effects fail.
- Embeddable Phoenix integration: host auth, host tenancy, host forms, host callbacks, host migrations.
- Real operator UX pressure: inboxes, ownership, actionable states, stale cases, and failed runs.
This makes Rift useful as a product while also forcing Squid Mesh APIs to prove they are understandable, durable, and practical inside normal Phoenix apps.
Build Rift as an embeddable Phoenix/LiveView ops inbox for Phoenix apps.
Users open host-configured cases through generated forms. Each case starts exactly one Squid Mesh workflow run. Operators review cases in an action inbox, claim or assign ownership, approve/reject/cancel waiting work, and inspect the linked runtime state through SquidSonar.
Rift owns case records, case events, assignment references, generated forms, lifecycle hooks, and operator UI. Host apps own authentication, tenant identity, actor identity, team meaning, selectable values, file storage, and domain-specific case definitions.
- Case submission
- /cases/new lists host-configured case types.
- /cases/new/:type renders a generated form from the selected CaseType.
- Submit creates a case, appends case_opened, starts the mapped Squid Mesh workflow/ trigger, stores squid_mesh_run_id, appends workflow_started, runs the CaseType.after_opened/2 hook, and redirects to detail.
- Originator view
- /cases/mine shows cases opened by the current actor.
- Detail shows public events, status, submitted data summary, comments, and visible attachment references.
- Operator action inbox
- / defaults to cases needing action: waiting approval, failed, failed side effect, or actionable by CaseType.
- Filters: status, type, team, assignee, updated time.
- Detail shows full timeline, internal notes, assignment controls, current run state, waiting reason, approve/reject/cancel actions, side-effect failures, and SquidSonar link/embed.
- Ownership
- Cases have optional assignee_ref.
- Operators can claim, release, or assign cases when host access allows it.
- Rift stores only actor references; host callbacks provide actor labels and permission meaning.
- Case lifecycle hooks
- Host-defined CaseType modules may implement hooks for after_opened, after_approved, after_rejected, after_cancelled, after_assigned, and after_released.
- Approve/reject/cancel call Squid Mesh first; hooks run only after the runtime action succeeds.
- Hook failures do not rollback accepted runtime actions. Rift appends side_effect_failed, marks the case actionable, and shows the failure in the operator inbox.
- Rift.Router
- rift "/ops/rift", otp_app: :my_app, resolver: MyApp.RiftResolver.
- Rift.Resolver
- resolve_actor(conn).
- resolve_access(actor).
- resolve_tenant(actor).
- resolve_case_types(actor).
- resolve_select_options(actor, case_type, field).
- optional display callbacks for actor labels and attachment URLs.
- Rift.CaseType
- stable type.
- display name, description, team.
- configurable form fields and validation.
- Squid Mesh workflow module and trigger.
- payload builder.
- allowed actor actions.
- optional lifecycle hooks returning :ok | {:ok, map()} | {:error, term()}.
Tables installed via mix rift.install:
- rift_cases
- id, tenant_key, type, subject, status, team
- opened_by_ref, assignee_ref
- state, details, squid_mesh_run_id
- timestamps
- indexes on tenant, type, status, team, assignee, run id, updated time.
- rift_case_events
- id, case_id, tenant_key, actor_ref
- type, data, visible_to_originator
- timestamps
- indexes on case, tenant, type, inserted time.
V1 event types:
- case_opened
- comment_added
- attachment_referenced
- workflow_started
- case_claimed
- case_released
- case_assigned
- case_approved
- case_rejected
- case_cancelled
- side_effect_completed
- side_effect_failed
- system_note
V1 statuses:
- draft
- open
- running
- waiting_for_approval
- approved
- rejected
- cancelled
- failed
- side_effect_failed
- completed
Status is cached on rift_cases for inbox queries and reconciled from Squid Mesh run inspection on detail reads.
- Router tests for mounted routes, invalid options, session data, and resolver fallback.
- Installer tests for mix rift.install: creates one current-schema migration and skips if already installed.
- Context tests for case opening, generated form validation, event creation, Squid Mesh start success/failure, lifecycle hook success/failure, claim/release/assign, approve, reject, cancel, and status reconciliation.
- LiveView tests for type picker, generated submit form, My Cases, action inbox filters, detail timeline visibility, ownership controls, side-effect failure display, and action button access.
- Integration smoke test in a minimal host app with one case type, one approval workflow, one rejection hook, one cancellation hook, SquidSonar mounted, and the full open → claim → wait → approve/reject/cancel → inspect flow.
- Stress scenarios for Squid Mesh: concurrent case openings, duplicate submissions, approval after cancellation, stale detail pages approving an already-terminal run, hook failure after accepted runtime transition, and run inspection after restart.
- Package name and repo are rift.
- Rift is embeddable first, with an optional standalone demo host for development.
- Host apps own authentication, tenancy, actors, teams, domain data, selectable values, file storage, side-effect implementation, and deployment.
- Case types are code-defined modules, not database-configured workflows.
- Each v1 case maps to exactly one Squid Mesh workflow run.
- V1 avoids replay, arbitrary unblock, visual workflow editing, built-in accounts, built-in uploads, generic help desk features, and built-in notifications.