Changelog
Unreleased: single-gateway architecture
Section titled “Unreleased: single-gateway architecture”A platform-wide architecture shift (ADR 0002), replacing the shape below piece by piece:
- One always-warm gateway (Container App) replaces per-app static-site hosting and per-app
Entra app registrations: every app now lives at
<app>.apps.<yourdomain>behind the gateway’s own OIDC session, gated by a pair of Entra groups instead of a per-app registration lock. - A remote MCP connector (claude.ai) or Claude Code as a native MCP client replaces the
old authentication plugin: no npm install and no device-code bootstrap. Four
release-matched organization skills (
sprig-publish,sprig-data,sprig-ops, andsprig-diagnostics) are downloaded fromAdmin > Setup > Skillsand uploaded separately by a Claude tenant administrator. - Ops-governed source exposure (
register_source/expose_entities) and a shared Data API builder instance replace direct browser-to-source access: every query, at build time and view time, streams through the gateway to the database under the caller’s own identity (on-behalf-of). - Group-based sharing (
approve_shareadds a group to an app’s viewers, no redeploy) replaces per-app Entra registration assignment. - App-to-source access is now a governed request: an app’s owner asks for a source
(
request_source_accessat any time, or asourceslist onprovision_app), Ops decides it (list_source_access_requests, thenapprove_source_accessorreject_source_accessover a whole batch of ids, andrevoke_source_accessfor one approved grant), and the approved request itself is the grant. Each source choosesmanualorautoapproval; deleting a source or retiring an app revokes its grants. The admin console includes the batch decision inbox, the per-source policy control, and each source’s approved-app inventory. Retiring and retired app groups are excluded from the source editor. Retirement persists source-owner revocations before changing source metadata, then returns typed Azure SQL or Fabric semantic runbooks on every retry until Ops confirms that the external work is complete. See App access to sources. - Ops can be notified when a request arrives instead of watching the inboxes. Point Sprig at a webhook (a Teams workflow trigger renders the card natively, and any HTTPS receiver can read the same facts) and toggle the two events independently. The URL is treated as a credential: stored securely, shown back masked, never logged, and accepted from a protected file rather than the command line. Receivers must resolve to public internet addresses. Delivery is best effort and at most once, with one five-second attempt, so the inboxes and the audit records remain the record. Configure it under Settings > Notifications, where Ops can replace the masked URL, toggle events, and send one explicit delivery test. See Notifications.
- Upgrades from the initial notification-settings build clear its database-stored webhook during
migration. Configure the webhook again with
--webhook-url-fileso Sprig stores it securely. - Source access is convergent and safe under concurrent administration. Requesting a
pair that is already approved succeeds and re-applies the grant instead of erroring,
so a failed configuration roll is repaired by simply retrying the request or
re-running the provision. Re-requesting a pair whose source has since stopped serving
is refused, naming the source’s state, rather than quietly re-applying it, and so is
approving one: an approve batch requires every named source to still be in service,
while rejecting stays available whatever the source’s state. Batch
decisions report one outcome per request (
applied,converged, orsupersededwith adetailnaming the concurrent winner), and a request lost to a concurrent decision, an app retirement, or an owner offboarding no longer discards the rest of the batch. Provisioning with several sources reports the same way: one outcome per source, so a source lost to a concurrent change is named in the response while the rest of the batch is filed and applied. A retired app cannot regain data access through any concurrent operation, approvals and revocations stay correct under simultaneous admin actions, and deployed data configurations are consistent across all platform instances. Provisioning an app while it is being handed to a new owner or published keeps both results: provisioning writes only what it owns. - Successful publishes and rollbacks now return the canonical app URL. App lists and status checks return it whenever an active version exists.
publish(app, files)andPOST /api/apps/{name}/publishhave been removed.begin_publish, raw archive uploads (the project source and the built bundle, both required), andcomplete_publishare now the only publishing workflow for every bundle. Completion verifies both archives, durably retains the source per version (resumable later viaget_app_source), pins verification and extraction to immutable uploads, is safe to retry across transient storage/pointer failures, and abandoned staging uploads or unactivated generated blobs become eligible for automatic cleanup after one day. Generated files are retained before their exact pointer can become active, so lifecycle cleanup excludes active and rollback artifacts.
This lands incrementally: some pieces (the gateway itself, standing it up in a real subscription end to end) are still catching up to the installer and the docs above it. The operate pages in this docs site describe the current, honest state of what’s automated versus what’s still a manual step.
0.1: Pilot
Section titled “0.1: Pilot”Initial pilot release.
- Governed publish: per-app Entra registrations (owner-locked), per-app static hosting in per-builder sandboxes, provenance tags, audit trail.
- Sharing via Ops approval;
Opsapp role. - Viewer-identity data access through the original browser-direct data API, with schema introspection and pagination support in the builder skill.
sprigCLI: aggregated Azure install (what-if → confirm → deploy → smoke).- Claude plugin with three skills (publish, data, ops), TypeScript sources, minified distribution.