Enaptive.Fuse.Api.Controllers 0.1.0
Enaptive Fuse
Fuse is the working-name Enaptive product for durable real-time approvals, PR/review approvals, pipeline approvals, security approvals, change-management approvals, supervisor overrides, pre-approvals, escalation chains, and agent secret-release gates.
Business identity:
- Fuse is an independently accountable product area for portfolio, launch, accounting, cost/revenue, customer, tenant, entitlement, support, and KPI rollups.
- The canonical implementation lives in
/Users/phirapara/Workspace/Fuse; any remainingEnaptive/Fusesource copy is transitional until the shared Enaptive API/worker host consumes Fuse through package/proxy/runtime integration. - The customer-facing web portal is
fuse.enaptive.com; Transform aggregates Fuse posture but is not the Fuse customer/admin/runtime surface. - The placement decision is documented in the Enaptive architecture ADR and the workspace area hierarchy standards.
Initial direction:
- approval-control product first,
- metadata/descriptor-driven gate registration,
- durable inbox/outbox-backed approval events and inbound actions,
- external secret-manager adapters before native secret storage,
- PR/review and pipeline approval coordination,
- security, SOX/non-SOX, and change-management approval coordination,
- parallel claim-first and first-decision-wins approval distributions,
- queue status, dwell time, SLA, and escalation analytics,
- Core candidate capture after reuse is proven,
- hosted Penpot-first design process for visible surfaces,
- product/business and partner/integration planning before external commercialization,
- mobile/web/desktop approval surfaces,
- watch approval companion surfaces,
- Orchestrate integration for agent tasks,
- Transform visibility for operating dashboards.
Current implementation status:
- first approval-engine skeleton exists under
Fuse/Core/Domain,Fuse/Core/Modules, andFuse/Core/Persistence, Fuse/Enaptive.Fuse.slnxbuilds the domain, module, persistence, API controller, CLI, and test projects; installable app hosts are built explicitly by target framework,- first slices cover create/list/approve/reject lifecycle, append-only audit records, canonical outbox events, signed/idempotent inbox action processing, provider capability manifests, tenant provider bindings, EF table mapping/repository/migration, and minimal shared-host API endpoints,
- worker module registration now includes a local/no-op Fuse dispatch worker scaffold for pending inbox/outbox rows,
- request-kind descriptors now seed the first approval gate vocabulary and allow new gates to be registered without changing the core lifecycle,
- approval requests now support queue actions for claim, release claim, defer, hold for review, and request changes in addition to approve/reject,
- approval queue projection now exposes status, dwell time, expiry posture, and requester context for operator/UI surfaces,
- approval queue health projection now summarizes active, claimed, breaching-soon, expired, escalated, max-dwell, and attention-list posture,
- approval request detail projection composes request state, queue posture, decisions, audit, metadata-only leases, outbox events, and timeline rows for read-only surfaces,
- approval leases can be listed and redeemed as metadata-only audited events without returning plaintext secrets,
- secret-release redemption now has metadata-only adapter routing for existing
op://references and Enaptive-nativeens://references, plus a first Enaptive Secrets metadata catalog seam that validates registered active references before consuming a lease, - Enaptive Secrets catalog metadata can be upserted and resolved through metadata-only Fuse API endpoints backed by Fuse EF persistence without storing or returning secret values,
- Enaptive Secrets encrypted value persistence primitives now store AES-256-GCM ciphertext records separately from metadata; release APIs still do not return secret values,
- Enaptive Secrets value bootstrap now accepts a plaintext value only long enough to encrypt it through a configured AES-256-GCM protector, persists ciphertext only, and returns a redacted write receipt,
- controlled Enaptive Secrets value release now uses an explicit
/redeem-valueendpoint after approved lease redemption, returns no-store responses, and fails before consuming a lease when metadata, ciphertext, or key configuration is missing, Fuse/Clinow provides the first agent/operator bridge for native Enaptive Secrets: agents usefuse secret request,fuse approval detail,fuse secret wait,fuse secret redeem-value, andfuse secret run; scoped approver routing can be supplied with--approveror--approvers, and operators usefuse secret bootstrap-value,fuse approvals pending --tenant <tenantUid> --approver <operatorUid>,fuse approval approve, andfuse approval rejectfor the first audited human decision path,- approval decisions now enforce the request's concrete identity approver plan server-side; actors outside the scoped approver roster, or requests that only have unresolved generic distribution targets, cannot approve/reject/claim/defer/hold/request changes,
- authenticated Fuse callers must also match tenant/requester claims when creating approval requests and tenant/operator actor claims before they can submit approval decisions or register mobile push devices for an operator; unauthenticated calls remain limited to the existing local-auth-bypass proof mode,
- approval decision surfaces are normalized into the canonical audit vocabulary (
mobile,desktop,watch,web,teams,api,worker,cli, plus provider surfaces such asgithub) so phone/desktop/watch evidence is comparable across channels, Fuse/App/Hostnow provides the first installable Fuse approval inbox scaffold for Mac Catalyst, iOS, and Android: operators can load pending requests, auto-refresh the visible inbox, and approve/reject without exposing secret values or redemption flows,- the installable app now requests pending approvals scoped to its configured tenant and operator actor UID so a device inbox only shows approvals addressed to that operator,
- local smoke proofs now cover scoped-approver CLI-only secret request/approval/redeem, iOS app-approved lease redemption, Mac app-approved process-only runtime injection, and iOS app-approved process-only runtime injection,
- local desktop/phone setup now has
Fuse/Scripts/prepare-local-device-approval-api.sh, which applies Fuse migrations, detects a LAN-reachable API URL, and prints the app connection settings for same-network approval testing, - manual installed-app proof now has
Fuse/Scripts/manual-local-app-agent-secret-run.sh, which creates a pending agent secret request and waits for an operator to approve from the Fuse app before verifying child-process-only secret injection, - provider inbox API can process already-normalized signed decision actions through the durable Fuse inbox path,
- provider adapter registry resolves webhook validators and inbound action normalizers by provider key before live adapters are introduced,
- provider webhook intake service validates and normalizes scaffolded signed webhooks before handing them to the durable inbox path,
- approval notification attempts now have a provider-agnostic durable ledger for idempotent queueing, hashed/reference-only delivery targets, retry state, sent state, and dead-letter posture before SignalR/email/Teams/mobile/watch dispatchers are introduced,
- first web notification dispatch proof now maps authorized SignalR hubs at the product-branded
/api/fuse/notifications/hubroute and the compatibility/api/enaptive/fuse/notifications/hubroute, publishing value-blind pending-approval envelopes from approval creation while recording sent/failed notification attempt state, - tenant evidence package preview now exposes a value-blind
/api/fuse/evidence/packages/previewread model, with/api/enaptive/fuse/evidence/packages/previewretained as a compatibility route, aggregating approval, provider-binding, mobile-registration, and notification-attempt counts without returning scopes, payload JSON, delivery hashes, credential references, webhook secret references, or secret values, Fuse/Portal/Hostnow has the first Blazor-first portal shell route at/fuse/blazor, a Blazor tenant admin overview at/fuse/blazor/admin/overview, a tenant settings map at/fuse/blazor/admin/settings, a read-only provider binding posture page at/fuse/blazor/admin/provider-bindings, a read-only notification posture page at/fuse/blazor/admin/notifications, a live read-only audit/evidence preview at/fuse/blazor/admin/audit-evidence, a read-only Blazor approval queue projection at/fuse/blazor/approvals, a guarded Blazor approval detail projection at/fuse/blazor/approvals/{approvalRequestUid}with approve/reject actions behind the same tenant/operator/status checks as the Razor detail page, and a read-only Blazor operator policy admin projection at/fuse/blazor/admin/policies/operator; the existing Razor Pages approval/admin routes continue to serve the deployed MVP while workflows migrate in place without changing the canonicalPortal/Hostsurface,- first hosted Penpot frame registry and local proof scaffold are documented in Fuse Hosted Penpot Design Artifacts,
- live mobile push has a production-safe readiness preflight in
Scripts/check-production-fuse-mobile-push-readiness.shthat validates API installation sync and worker dispatch configuration without printing Azure connection strings or sending notifications, - production Fuse schema application and hosted app proof are covered by the Fuse Remote MVP Operator Runbook, including the one-shot worker posture using
Enaptive:FuseDispatchWorker:MigrateOnStartup=true; actual production migration still requires explicit operator approval and rollback/backup posture, - live provider adapters, email/Teams/watch dispatchers, richer agent runtime injection/polling, push/watch approval companions, and hosted Penpot canvas ids remain follow-up work.
- Fuse website preview and content operations are planned as an MVP-adjacent launch-readiness track in Fuse Website Preview And Content Operations Plan; the preview should live on the Enaptive website behind a hidden/noindexed access gate before public launch.
Enaptive Secrets value bootstrap requires one of:
Fuse:EnaptiveSecrets:EncryptionKeyBase64FUSE_ENAPTIVE_SECRETS_ENCRYPTION_KEY_BASE64
The key must be a base64-encoded 32-byte value. Fuse:EnaptiveSecrets:EncryptionKeyVersion or FUSE_ENAPTIVE_SECRETS_ENCRYPTION_KEY_VERSION can identify the active key version. Without a configured key, value bootstrap fails closed.
For local smoke testing with the source-backed API LaunchAgent, set a non-production key in the user launchd environment and restart the API:
launchctl setenv FUSE_ENAPTIVE_SECRETS_ENCRYPTION_KEY_BASE64 "$(openssl rand -base64 32)"
launchctl setenv FUSE_ENAPTIVE_SECRETS_ENCRYPTION_KEY_VERSION local-smoke-k1
Api/Server/Host/server.sh restart
Use this only for local test values. Production keys must come from the approved Enaptive Secrets/key-management path.
Hosted Fuse API-key identity binding:
- Core authenticates
X-API-Keycallers through the shared API-key handler. - Fuse binds authenticated API-key identifiers to product-local identities through
Fuse:CallerIdentity:ApiKeyBindings. - Bindings reference only API-key ids or names, never raw key values.
- Agent keys should set
TenantUid+RequesterUid; approver app keys should setTenantUid+OperatorUid. - This is the remote-MVP bridge for a hosted Fuse API until full app/user sign-in replaces operator API keys.
- Production systemd environment variable names must use environment-safe key identifiers such as
FuseAgentCodexandFusePareshApp; do not use hyphenated dictionary keys such asfuse-agent-codexin/etc/enaptive/api-server.env. - Use
Fuse/Scripts/provision-hosted-remote-mvp-api-keys.sh --applyto rotate/provision the hosted MVP keys without printing generated values.
Before local smoke proofs exercise Fuse APIs, run the local Fuse migration helper or let the smoke scripts run it automatically:
./Fuse/Scripts/apply-local-fuse-migrations.sh
Set FUSE_SKIP_LOCAL_MIGRATIONS=1 only when the target database schema is already known to be current.
Agent CLI proof:
printf '%s' "$NON_PRODUCTION_TEST_VALUE" | \
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
secret bootstrap-value \
--ref ens://tenant-1/local/fuse/agent-codex/penpot-token \
--created-by user-paresh \
--key-version local-smoke-k1 \
--stdin
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
secret request \
--ref ens://tenant-1/local/fuse/agent-codex/penpot-token \
--agent agent-codex \
--reason "Codex needs a scoped Penpot token." \
--approver user-paresh \
--approver-name "Paresh"
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
approvals pending \
--tenant tenant-1 \
--approver user-paresh
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
approval detail <approvalRequestUid>
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
approval approve <approvalRequestUid> \
--actor user-paresh \
--name "Paresh" \
--reason "Approved scoped agent proof."
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
secret wait \
--request <approvalRequestUid>
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
secret redeem-value \
--lease <leaseUid> \
--agent agent-codex \
--env-name PENPOT_TOKEN \
--env-file .secrets/fuse-agent.env
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
secret run \
--ref ens://tenant-1/local/fuse/agent-codex/penpot-token \
--agent agent-codex \
--env-name PENPOT_TOKEN \
--reason "Codex needs a scoped Penpot token for one child process." \
-- \
./Scripts/run-agent-task.sh
The CLI intentionally does not accept plaintext secret values as command-line arguments and does not print bootstrap or redeemed secret values. secret bootstrap-value reads an operator-supplied value from --stdin or a hidden interactive prompt, upserts metadata, encrypts the value through the Fuse API, and prints only a redacted receipt. secret redeem-value writes an approved value to a caller-selected env file with user-only permissions where supported. secret run avoids the env file and injects the approved value only into the launched child process environment.
Operator notification diagnostics are value-blind:
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
notifications registrations \
--tenant tenant-1 \
--operator user-paresh
dotnet run --project Fuse/Cli/Enaptive.Fuse.Cli.csproj -- \
notifications list \
--tenant tenant-1 \
--status Failed
The registration command confirms which mobile approval devices are registered for a tenant/operator without printing native APNS/FCM tokens, persisted token hashes, or provider installation ids.
Fuse/Scripts/manual-hosted-app-agent-secret-run.sh runs this registration diagnostic automatically when FUSE_OPERATOR_API_KEY is set; set FUSE_REQUIRE_PUSH_REGISTRATION=1 only when you want the hosted proof to fail unless a mobile push registration is active.
Fuse App proof:
FUSE_API_URL=http://127.0.0.1:4001 \
FUSE_OPERATOR_ACTOR_UID=user-paresh \
FUSE_OPERATOR_DISPLAY_NAME=Paresh \
dotnet build Fuse/App/Host/Enaptive.Fuse.App.Host.csproj -c Debug -f net10.0-maccatalyst
The first app surface is intentionally approval-only. It calls the Fuse approval queue and approve/reject endpoints, auto-refreshes while the inbox is visible, but does not redeem leases, print secret values, or store secret material. Installed app settings can be changed inside the approval inbox. Non-secret endpoint/operator settings use platform preferences; the optional API key is saved through platform secure storage. Use Test connection after entering a hosted endpoint/API key to verify the protected tenant/operator approval queue scope before waiting on a real request.
For a physical phone or another desktop on the same network, prepare the local API and copy the printed connection settings into the Fuse app:
Fuse/Scripts/prepare-local-device-approval-api.sh --check
Fuse/Scripts/prepare-local-device-approval-api.sh --start
Use the printed http://<mac-lan-ip>:4001 API base URL only for local development proof. Keep the device on the same network, allow incoming connections for dotnet if macOS prompts, and do not use production secrets while the development API is exposed on the LAN.
Local app launch/install helpers:
cd Fuse/App/Host
./run-mac.sh
./run-android-emulator.sh
./install-mac.sh --yes --configure-local --open
./install-ios-device.sh --device <iphone-udid-or-name> --launch
--configure-local seeds only non-secret macOS preferences for the installed Mac app (http://127.0.0.1:4001, tenant, and operator identity). It intentionally does not write API keys; use the in-app settings panel if a hosted/protected API requires one.
install-ios-device.sh uses Xcode devicectl for a connected physical iPhone/iPad. --launch passes non-secret local proof settings only for that launch; save settings in the app for future launches. If the device is locked, install still succeeds and the helper prints the exact relaunch command; set FUSE_IOS_REQUIRE_LAUNCH=1 when a strict launch failure should fail automation. The helper disables iOS push entitlements by default so wildcard development profiles can install the approval inbox; set FUSE_IOS_INCLUDE_PUSH_ENTITLEMENTS=1 only when the selected Apple profile includes APNS.
Simulator smoke tests:
appium --base-path /
dotnet build Fuse/App/Host/Enaptive.Fuse.App.Host.csproj -c Debug -f net10.0-ios -p:RuntimeIdentifier=iossimulator-arm64
FUSE_RUN_APPIUM=1 \
FUSE_APPIUM_PLATFORM=ios \
FUSE_APPIUM_DEVICE_NAME="iPhone 17" \
FUSE_APPIUM_APP="Fuse/App/Host/bin/Debug/net10.0-ios/iossimulator-arm64/Enaptive.Fuse.App.Host.app" \
dotnet test Fuse/App/AppiumTests/Enaptive.Fuse.App.AppiumTests.csproj -c Release
Use the repo-local simulator startup smoke when Appium/WebDriverAgent is not needed:
Fuse/App/Host/smoke-ios-simulator-start.sh
Use the seeded approval smoke to prove the native app can approve a real pending Fuse request against the local API:
Fuse/App/Host/smoke-ios-simulator-approval-flow.sh
This script creates a metadata-only Enaptive Secrets approval request, drives the iOS simulator app through Appium, taps Approve, and verifies that Fuse issued the lease. It does not redeem or print secret values.
Use the Mac Catalyst seeded approval smoke for the same proof on the desktop surface:
Fuse/App/Host/smoke-mac-approval-flow.sh
The Mac script builds the desktop app, drives it through the Appium Mac2 driver, and verifies the issued lease without redeeming or printing secret values. If Mac2 reports interactive Automation Mode authentication, run this once on the workstation before the desktop smoke:
automationmodetool enable-automationmode-without-authentication
Local MVP smoke:
FUSE_API_URL=http://127.0.0.1:4001 \
./Fuse/Scripts/smoke-local-agent-secret-approval.sh
For non-interactive runs, set FUSE_MVP_SECRET_VALUE to a non-production test value. The smoke script reads interactive values with a silent prompt and uses the CLI for request, approve, wait, and redeem.
App-approved secret-release smoke:
FUSE_API_URL=http://127.0.0.1:4001 \
FUSE_MVP_SECRET_VALUE="non-production-test-value" \
FUSE_IOS_SIMULATOR_UDID=<simulator-udid> \
./Fuse/Scripts/smoke-ios-app-agent-secret-release.sh
This is the first full native approval proof for agent secret access: the script bootstraps an encrypted Enaptive Secrets test value, creates an agent approval request, uses the iOS simulator app as the human approval surface, waits for the lease, and redeems the value into a local env file for the requesting agent process. The app never sees, stores, redeems, or prints secret values.
Mac app-approved runtime-injection smoke:
FUSE_API_URL=http://127.0.0.1:4001 \
FUSE_MVP_SECRET_VALUE="non-production-test-value" \
./Fuse/Scripts/smoke-mac-app-agent-secret-run.sh
This is the desktop companion proof for agent secret access: the script bootstraps an encrypted Enaptive Secrets test value, starts fuse secret run, uses the Mac Catalyst app as the human approval surface through Appium/Mac2, and verifies the child process receives the approved value only through its environment. It does not create an env file, display the value, or print the value.
iOS app-approved runtime-injection smoke:
FUSE_API_URL=http://127.0.0.1:4001 \
FUSE_MVP_SECRET_VALUE="non-production-test-value" \
FUSE_IOS_SIMULATOR_UDID=<simulator-udid> \
./Fuse/Scripts/smoke-ios-app-agent-secret-run.sh
This is the phone-surface companion proof for agent secret access: the script bootstraps an encrypted Enaptive Secrets test value, starts fuse secret run, uses the iOS simulator app as the human approval surface through Appium, and verifies the child process receives the approved value only through its environment. It does not create an env file, display the value, or print the value.
Manual installed-app approval proof:
FUSE_API_URL=http://127.0.0.1:4001 \
FUSE_MVP_SECRET_VALUE="non-production-test-value" \
./Fuse/Scripts/manual-local-app-agent-secret-run.sh
This is the first hands-on Fuse MVP test for an installed desktop or phone app. The script prepares the local API/device settings, bootstraps an encrypted non-production test value, starts fuse secret run, prints the approval request UID, and waits while the operator approves from the Fuse app. After approval, the waiting child process receives the secret through environment injection only; the app never sees the value and the script refuses to print logs if the value appears.
Hosted installed-app approval proof:
Use the canonical Fuse Remote MVP Operator Runbook for the full hosted sequence, including migration posture, API-key provisioning, app install/configuration, readiness checks, and cleanup.
First verify hosted API-key binding readiness without secret values. The readiness script creates and rejects a value-blind request, checks approval detail, notification diagnostics, and operator-scoped queue visibility, and fails if the generated ens:// reference appears in diagnostic output:
Fuse/Scripts/provision-hosted-remote-mvp-api-keys.sh --apply
FUSE_API_URL="https://api.enaptive.com" \
FUSE_AGENT_API_KEY="$FUSE_AGENT_API_KEY" \
FUSE_OPERATOR_API_KEY="$FUSE_OPERATOR_API_KEY" \
./Fuse/Scripts/check-hosted-remote-mvp-readiness.sh
For a connected iPhone/iPad, install and launch the app with hosted non-secret settings only:
Fuse/App/Host/install-ios-device.sh \
--device "$FUSE_IOS_DEVICE_ID" \
--hosted \
--tenant "$FUSE_MVP_TENANT_UID" \
--operator "$FUSE_MVP_APPROVER_UID" \
--operator-name "$FUSE_MVP_APPROVER_NAME" \
--launch
Paste the hosted operator API key in the app, tap Test connection, then save the connection settings.
For a non-mutating app setup preflight, print the exact non-secret app settings and check the hosted operator scope/device registration posture:
FUSE_API_URL="https://api.enaptive.com" \
FUSE_AGENT_API_KEY="$FUSE_AGENT_API_KEY" \
FUSE_OPERATOR_API_KEY="$FUSE_OPERATOR_API_KEY" \
./Fuse/Scripts/check-hosted-app-connection-readiness.sh
Then run the secret-bearing installed-app proof:
FUSE_API_URL="https://api.enaptive.com" \
FUSE_AGENT_API_KEY="$FUSE_AGENT_API_KEY" \
FUSE_OPERATOR_API_KEY="$FUSE_OPERATOR_API_KEY" \
./Fuse/Scripts/manual-hosted-app-agent-secret-run.sh
Set FUSE_MVP_SECRET_REF to a preloaded ens://... reference for normal hosted use; the script checks metadata for that reference before creating an approval request but redacts the reference from its own banner and error output. For a non-production bootstrap proof only, also set FUSE_MVP_SECRET_VALUE and FUSE_SECRET_BOOTSTRAP_API_KEY; the script sends the value through stdin to Fuse encryption and refuses to print logs if the value appears. FUSE_AGENT_API_KEY should map to RequesterUid=agent-codex; the app/operator key should map to OperatorUid=user-paresh through Fuse:CallerIdentity:ApiKeyBindings. The hosted script also reads value-blind approval detail and notification diagnostics for the created request, failing if the detail output exposes the secret reference. When FUSE_OPERATOR_API_KEY is available, the script also verifies that the redacted operator-scoped queue can see the request before waiting on app approval; otherwise, use the app's Test connection action.
Start with:
No packages depend on Enaptive.Fuse.Api.Controllers.
.NET 10.0
- Enaptive.Fuse.Modules (>= 0.1.0)
- Enaptive.Fuse.Persistence (>= 0.1.0)
- Microsoft.Azure.NotificationHubs (>= 4.2.0)
| Version | Downloads | Last updated |
|---|---|---|
| 0.1.0 | 2 | 06/18/2026 |