Skip to main content

Universal Connections M365 Pre Sandbox

Sandbox and pre-pilot how-to

Read-only Microsoft 365, step by step, without a live claim.

This page walks an owner through the delegated Microsoft 365 connection as it runs in the development sandbox today: Entra app, consent per lane in Lantern, verification, troubleshooting and revocation. It is not the customer onboarding path.
Readiness (Fabric contract)uc_readiness_score: 7.0 of 7 (100.0 %)uc_readiness_state: repo_readyrepo_ready: yessandbox_required: yeslive_ready: no

Overview and status​

Universal Connections (UC) lets a Helpifyr agent read from Microsoft 365 on behalf of one signed-in owner. The connection uses delegated Microsoft Graph permissions only, and it has four separate consent lanes:

LaneDelegated permissionConsent callLease permission set
FilesFiles.Read (plus offline_access and openid)lane=files (default when lane is omitted)Files.Read
MailMail.Read (plus offline_access and openid)lane=mailMail.Read
SendMail.Send (plus offline_access and openid)lane=sendMail.Send
DraftMail.ReadWrite (plus offline_access and openid)lane=draftMail.ReadWrite

The consent flow now has four closed lanes: files, mail, send and draft. The sandbox measurements reached an active lease for each lane (#3682, comments 237134 and 237783), but a lease is not a provider side effect. The send and draft operations are not live, see Send and draft stages.

What this page covers, and what it does not​

  • This is the sandbox / pre-pilot path: a development Microsoft 365 tenant, one owner session, one folder (Files) and one mailbox (Mail), both mapped on the server side, not chosen in the browser.
  • The customer path is different. The product decision is that Stalwart is the standard installation and that a customer can later activate Microsoft 365 through Lantern, including the install wizard; from then on Microsoft 365 becomes the source of truth for mail. That wizard does not exist yet, so until it ships, this page describes the sandbox only.
  • Sending mail, drafts, writing files, subscriptions and webhooks are not live side effects in this how-to. Admin consent for Mail.Send and Mail.ReadWrite was granted in the sandbox tenant on 2026-10-02, and all four consent lanes reached an active lease, but no draft was created and no mail was sent. The send and draft stages remain guarded and not fully deployed end to end, see Send and draft stages.

The Owner decided on 2026-10-02 to bring the send stage forward for the sandbox tenant, and to create drafts through Microsoft Graph createDraft. The send and draft consent lanes both reached an active lease in the sandbox (#3682, comments 237134 and 237783). No mail was sent and no draft was created. The downstream operations are not yet fully deployed end to end: Fabric F2 is merged to main, complete-set revocation follow-up #3711 is merged to main, and the current open rollout/migration follow-up is #3714; the deployment rollout remains on the older revision with the required migration/table state absent (#3710, comments 238118, 238326, 238150 and 238154). live_ready stays no.

StageDelegated permissionAdmin consent in the sandbox tenantKeystore broker laneConsent call in Heddle and Lantern
SendMail.SendGranted on 2026-10-02Active sandbox lease measuredWired; request scope openid Mail.Send offline_access; no mail was sent.
DraftMail.ReadWriteGranted on 2026-10-02Active sandbox lease measuredWired; request scope exactly openid Mail.ReadWrite offline_access; no draft was created.

What is fixed by the Owner decisions and by the measurements:

  • Sandbox first, no silent switch-on. The capability is built generally and proven in the sandbox tenant first. Activation per tenant stays bound to an Owner go-ahead, the tenant's own admin consent, the guarded-send gates and human approval.
  • Guarded send, mode sandbox_live. One recipient from an allow-list, no attachment, no bulk, and a mandatory reference to the Owner go-ahead for every single mail (a chat yes to recipient and text). production_send_enabled and live_ready stay false.
  • Approval rights. The sandbox owner persona gets two entitlements for the send path (capability execute and a mail-send approval right), for the sandbox only.
  • Consent order that was followed. The Keystore broker tolerance for a reported Mail.Send went live first, then the Owner granted admin consent for Mail.Send, then the broker lanes send and draft and the token-read routes were rolled out, then the Owner granted admin consent for Mail.ReadWrite. The four lanes were measured through active leases; the downstream Weft/Fabric operations remain guarded and not live.
  • openid listed explicitly. openid was granted but missing from the configured permission list; it was added to the list before the consent, because a tenant-wide consent can revoke granted permissions that are not listed.
  • One Entra app with tolerance for now. The residual risk is measured, see What the token carries. Two Entra apps are required before the first customer tenant.

Status from the readiness contract​

The official result is read from contracts/extensions/m365_readiness_gate_v1.json in Fabric (contract version 1.1.0, observed 2026-09-24T09:52:59Z). This page does not keep a second status ledger.

FieldValue
readiness.staterepo_ready
repo_readytrue
candidate / in_buildfalse / false
live_readyfalse
Score (equal weights, seven gates)7.0 of 7 (100.0 %)

The seven gates (platform admission, authority chain, provider connection, authority binding, mail read, evidence store, isolation and denial) are each recorded as live through sandbox receipts. The score counts evidenced gates. It is not a production claim, and live_ready stays no. As recorded in the tracking issues when this page was written (2026-10-02), these live proofs are still open (the scp scope list of a refreshed token has been recorded since, see What the token carries):

  • Reading through a persisted connection created with the Lantern connections API (not only through operator scripts).
  • The revoke drill, and the Microsoft-side revocation step in the runbook.
  • Mapping an expired consent (invalid_grant) to reauthorization_required.
  • A second tenant and principal for the denial matrix (5 of 32 vectors are live, in one tenant).
  • A write and read-back path for the evidence store.

Prerequisites​

You need:

  1. A Microsoft 365 sandbox tenant with a user who owns the folder or mailbox to read. The Fabric activation contract records an E5 developer sandbox with synthetic users. Do not use a customer or production tenant.
  2. An Entra administrator who can register an application and grant admin consent for the tenant.
  3. A Lantern owner session in the browser you will use. The consent start requires it, and the whole consent must finish in that same browser.
  4. An operator who has configured the deployment: the tenant ID and client ID of the Entra app (LANTERN_M365_TENANT_ID, LANTERN_M365_CLIENT_ID), the server-side mapping for the folder (Files) or the mailbox and its resource scope (Mail), and the client secret in Keystore custody.

This page uses the placeholders <tenant-id>, <client-id> and <lantern-host>. Never paste real tenant IDs, client IDs, secrets or token values into tickets, chats or repositories.

Time windows to plan for​

Several short windows run during one consent. The tightest one is 300 s from the authorize call to the handoff, so do not leave the Microsoft dialog open.

WindowValueWhat it bounds
Lantern initiation record300 sFrom the authorize call until Heddle's handoff reaches Lantern. After that the initiation is expired and Lantern refuses it.
Consent state in Heddle600 sThe state, nonce and PKCE record and the state cookie.
Handoff after Microsoft's form post120 sThe single browser round trip to the completion URL.
Microsoft authorization codeabout a minuteA staged code must be redeemed within about a minute of issue.
Keystore exchange120 s timeoutLantern waits this long for the exchange; the exchange was measured at 26-90 s.
Lease900 sLifetime of an access lease, from the exchange or from each refresh.
Lantern session cookie3600 sOne hour. After that you must sign in to Lantern again.

Set up the Entra app​

Microsoft's portal labels may change. The values below come from the Fabric contracts and the consent code, not from the portal.

  1. Register an application in Microsoft Entra ID. Choose a single-tenant account type (single_tenant, this organizational directory only). The permission manifest suggests the display name "Helpifyr Universal Connections - M365 Sandbox".
  2. Add exactly one redirect URI under a Web platform: https://<lantern-host>/api/v1/lantern/connections/m365/callback. Entra and Helpifyr compare it by exact match. The consent code pins this URI as a constant and does not read it from configuration, so a different Lantern host needs a code and contract change, not only an Entra change. The flow is a confidential-client flow: Keystore redeems the code with a client secret, and the authorize request uses response_mode=form_post.
  3. Check the authentication flags. The Fabric activation contract records implicit access, implicit ID-token and public-client flows as disabled. The consent code requests response_type=code id_token (a hybrid flow), so Microsoft may require ID-token issuance on the app. The same contract still records hybrid_id_token_flow as disabled (readback of 2026-09-18, before the hybrid flow was built). Treat this as a known contract drift and confirm the setting in the sandbox before the first consent.
  4. Add delegated Microsoft Graph permissions: Files.Read, Mail.Read, Mail.Send, Mail.ReadWrite, offline_access and openid. Add no application permissions. List openid explicitly: a tenant-wide admin consent can revoke granted permissions that are not in the list. The four consent lanes request their own closed scope set; they do not merge into one request or grant application permissions. See Send and draft stages.
  5. Grant admin consent for the listed permissions. In the sandbox the app has Files.Read and Mail.Read admin-consented, and since 2026-10-02 also Mail.Send and Mail.ReadWrite, which is why Microsoft can complete a lane's consent without a click. The Fabric activation contract originally recorded admin consent as not_required (Files.Read only, 2026-09-18). That record is outdated for the four-lane setup. The side effect of granting both is described under Option C below.
  6. Create one client secret and hand it to Keystore custody. Keystore reads it through an opaque reference (M365_OAUTH_CLIENT_CREDENTIAL_REF); Lantern and Heddle never hold it.
  7. Record Conditional Access. The permission manifest requires a Conditional Access readback before a live claim (the sandbox readback recorded zero policies).
  8. Give the operator the tenant ID and client ID (<tenant-id>, <client-id>) through the operator's own secure channel.

Screenshot slot M365-S01 (pending)

Caption: Entra app registration, Authentication page: one Web redirect URI ending in /api/v1/lantern/connections/m365/callback; tenant ID and client ID blurred.

Provided by: owner session in the Entra portal (open until delivered).

Screenshot slot M365-S02 (pending)

Caption: Entra app registration, API permissions page: delegated Microsoft Graph Files.Read, Mail.Read, Mail.ReadWrite, Mail.Send, offline_access and openid, all with admin consent granted; tenant ID and client ID blurred. Planned image files (blurred by the coordinator, committed separately): m365-s02-api-permissions-before.png, m365-s02-api-permissions-after-mail-send.png, m365-s02-api-permissions-after-mail-readwrite.png.

Provided by: owner session in the Entra portal (open until delivered).

Give consent once per lane. Each lane uses the same call with a different lane value, and each lane produces its own lease. A Mail consent never reuses the Files lease; the four lanes have separate leases.

Files lane​

  1. Sign in to Lantern as the owner. The Integrations page lists the connections (see the next screenshot slot).
  2. In the same browser, open https://<lantern-host>/api/v1/lantern/connections/m365/authorize?lane=files. Leaving out lane selects the Files lane.
  3. The browser is redirected to Microsoft with the scope openid Files.Read offline_access, a PKCE S256 challenge, a state and a nonce.
  4. Sign in and approve. Microsoft may show an account picker, see Troubleshooting.
  5. The browser returns to Lantern and shows handed_off. Do not reload, go back or reopen the final URL.

Mail lane​

  1. Repeat the steps above with https://<lantern-host>/api/v1/lantern/connections/m365/authorize?lane=mail.
  2. The scope is openid Mail.Read offline_access. The mailbox and its resource scope come from the server-side mapping. If that mapping is incomplete, the call stops with canonical_account_mapping_required.
  3. Any other lane value is rejected before a session, state or cookie is touched.

Send lane​

  1. Use the same owner session and open https://<lantern-host>/api/v1/lantern/connections/m365/authorize?lane=send.
  2. The measured request scope is openid Mail.Send offline_access; successful consent reaches an active Mail.Send lease.
  3. This consent does not send mail. Sending remains behind the guarded Fabric/Weft path, Owner approval and the pending rollout gates.

Draft lane​

  1. Use the same owner session and open https://<lantern-host>/api/v1/lantern/connections/m365/authorize?lane=draft.
  2. The measured request scope is exactly openid Mail.ReadWrite offline_access; successful consent reaches an active Mail.ReadWrite lease.
  3. This consent does not create a draft. Draft creation remains behind the downstream operation path and is not live.

Screenshot slot M365-S03 (pending)

Caption: Lantern Integrations page showing the connection list in the sandbox, before the consent call; account details masked.

Provided by: Coordinator capture with an owner login.

Screenshot slot M365-S04 (pending)

Caption: Microsoft consent dialog or account picker ("Pick an account") during the Mail lane consent; tenant and user details blurred.

Provided by: Coordinator capture with an owner login.

Screenshot slot M365-S05 (pending)

Caption: Browser answer after a successful consent: the handoff response with status handed_off.

Provided by: Coordinator capture with an owner login.

  1. Heddle checks the Lantern session, creates state, nonce and a PKCE verifier, hands the verifier to Keystore and asks Lantern for an initiation record.
  2. Microsoft posts the result to the callback. This is a cross-site POST, so Heddle only stores the body for up to 120 s and answers with a 303 redirect to a completion URL. It makes no trust decision at this step.
  3. The completion URL is a same-site navigation. Heddle now checks the state cookie, the Lantern session, the nonce, and the ID token (signature, issuer, audience, tenant, nonce). A handoff id and a state can each be used once.
  4. Heddle stages the authorization code with Keystore, resolves the initiation at Lantern, and sends Lantern an HMAC-signed handoff that carries only opaque references.
  5. Lantern calls the Keystore exchange once. Keystore redeems the code with the client secret and creates a lease (generation 1, 900 s). The raw code, the verifier and the tokens are never logged and never returned to the browser.

What the token carries (Option C)​

Keystore redeems the code without a scope parameter, so Microsoft returns every consented resource scope. A refresh sent with the lane scope also returns the other consented scopes. The owner decided on Option C for the pilot: the broker tolerates a surplus that is a subset of Files.Read and Mail.Read at refresh, logs the names of the surplus scopes, and keeps rejecting every other scope. Since 2026-10-02 the tolerated set also contains Mail.Send and Mail.ReadWrite. A refresh requests Mail.Send only for a lease of the lane send and Mail.ReadWrite only for a lease of the lane draft; the lanes files and mail never request them.

Residual risk, named, measured and accepted by the owner for the sandbox: the token of the Mail lane carries more than its lane. A Mail lease refreshed to generation 2 on 2026-10-02 (after both admin consents) has the token claim scp Files.Read, Mail.Read, Mail.ReadWrite, Mail.Send, openid, profile, email, and the broker logged surplus_scopes=Files.Read,Mail.ReadWrite,Mail.Send. Consequence: a leaked Mail access token can additionally read files, and with the two new consents also change and send mail, as the consenting user. Files.Read is wanted (OneDrive reading); the rest is the price of one Entra app with tolerance. In this mode the lane limit lives in the lease metadata (permission_set) and in Weft and Fabric, not in the token, and the planned human approval is the further gate. Two Entra apps with a hard separation are required before the first customer tenant (Option A, an owner action in the customer tenant); the tolerance can be switched off with M365_REFRESH_TOLERATE_CONSENTED_RESOURCE_SCOPES.

Verify​

  1. Browser answer. A successful consent ends with the response handed_off and the detail m365 consent handoff accepted by Lantern. A deployment without the Lantern handoff configured answers with staged instead.
  2. Operator logs. Heddle logs m365_consent_callback_exit with outcome=staged. Lantern logs lantern.m365_exchange_outcome with the lease generation and opaque references only. Keystore logs exchange_step lines up to issued. No log line contains a code, verifier or token value.
  3. Repository checks without a live call:
    • python scripts/verify_universal_connections_m365_sandbox_activation.py --check
    • python -m pytest -q tests/test_universal_connections_m365_sandbox_activation.py
  4. Read check. The sandbox read of the Mail lane returned allowed_read_only with zero write, send and subscription calls, and a replay without a second provider call. Run the read inside the 900 s lease window.

A passing verification shows that the sandbox path works. It does not change live_ready.

Troubleshooting​

Messages appear in a browser JSON answer, in the Lantern UI, or only in operator logs.

MessageWhereCauseWhat to do
authenticated lantern session requiredAuthorize call, HTTP 401, field detailThe browser has no valid Lantern session.Sign in to Lantern again, then repeat the authorize call.
authenticated_lantern_session_requiredCompletion step, HTTP 401The session is gone or differs from the one that started the consent (different browser or profile, or the cookie expired after 3600 s).Sign in again and start over in one browser.
authenticated_lantern_session_cookie_missingHeddle session checkThe Lantern session cookie was not sent at all.Allow cookies for the Lantern host and sign in again.
access_context_unavailableLantern UI, from the access-context callLantern could not resolve your access context. HTTP 401 means the session is not accepted; 502 or 503 mean the upstream is unavailable or its contract drifted. The BFF logs lantern.access_context_unavailable.Sign in again. If it persists, the operator checks the BFF log line.
invalid_or_expired_stateCompletion step, HTTP 400The state cookie is missing or does not match, the state is older than 600 s, it was already used, or Heddle restarted (the store is in memory).Start again from the authorize call, in the same browser, and finish quickly.
invalid_or_expired_handoffCompletion step, HTTP 400The handoff is older than 120 s, was already used (reload or back button), or is unknown.Start again. Never reopen the completion URL.
lantern_handoff_failedCompletion step, HTTP 502The consent was consumed, but Lantern or Keystore rejected the handoff. The cause code is only in the Heddle log.Start a new consent. The staged references are not returned.
Expired or used codeOperator logsKeystore rejects with expired authorization code, unstaged, consumed, or revoked authorization code or authorization code replay blocked. Its HTTP answer is the generic invalid_or_unavailable_handoff. Microsoft itself may answer invalid_grant. The code is single-use and lives about a minute.Start a new consent. An exchange with an unknown outcome is terminal, so never retry the same handoff.
exchange_timeoutLantern handoff answerThe Keystore exchange did not answer within 120 s. The one-time code may already be consumed.Start a new consent.
Pick an accountMicrosoft pageMicrosoft shows an account picker, sometimes after admin consent. It is Microsoft's page, not Helpifyr's. In the sandbox a lane consent also completed once without any click.Pick the sandbox user this connection is meant for.
scope_widening_rejectedKeystore log, at refreshSee below.See below.
consent_denied_or_provider_errorCompletion step, HTTP 400The callback carried an error instead of a code, for example because the consent was cancelled.Start again and approve.
canonical_account_mapping_requiredLantern authorize, HTTP 424The server-side mapping for the lane is incomplete (for Mail: mailbox and resource scope).Operator completes the mapping.
missing_tenant_or_client_idAuthorize call, HTTP 503Tenant ID or client ID is not configured (detail m365 consent lane is not configured).Operator configures the Entra app values.

scope_widening_rejected​

Keystore logs scope_widening_rejected surplus_count=1 and fails the refresh with the message token endpoint returned more resource scopes than the admitted permission set. The lease stays on its old generation and expires after 900 s, so reading stops until you consent again.

  • Cause with the pilot default: the token response contained a scope outside the tolerated set (Files.Read and Mail.Read in the pinned pilot state; since 2026-10-02 also Mail.Send and Mail.ReadWrite), for example Files.ReadWrite.All or any *.All scope. This is the guard doing its job. Do not widen the admitted set.
  • Cause with the tolerance switched off: every refresh fails while the app has both rights consented, because Microsoft returns both. This is the strict mode that Option A will restore with one app per lane.
  • With the tolerance on, a Files.Read surplus on a Mail lease is not a failure. Keystore logs scope_widening_tolerated_at_refresh with the scope names. That log line is the visible form of the Option C residual risk, so do not hide it from reviewers.

A refresh took about 65 s in the sandbox on 2026-10-01 and about 95 to 100 s on 2026-10-02, so use a client timeout well above that when you call it by script (the sandbox probe uses 120 s).

Revoke and roll back​

  • Stop one lease. An operator calls the broker route /internal/m365/oauth/revoke with the lease reference and generation. The lease becomes revoked, and its access and refresh references are revoked. Refresh and reads then fail with stale or revoked generation blocked. A stale generation is refused.
  • Let it lapse. Without a refresh a lease ends after 900 s and later calls fail with expired lease blocked.
  • Consent again. After a revoke, a new consent needs a new code, state, nonce and PKCE verifier.
  • Restore strict scope checking. Set M365_REFRESH_TOLERATE_CONSENTED_RESOURCE_SCOPES to off to end the Option C tolerance without a code change.
  • Remove the Microsoft side. Remove the app's delegated consent or the app registration in the Entra portal. This step is still open in the runbook, and the revoke drill has not run live yet, so treat both as unmeasured. The activation runbook names five rollback steps: rollback-stop-read, rollback-revoke-connection, rollback-revoke-lease, rollback-remove-registration and rollback-closeout.
  • Roll back the broker. Remove the broker service from the active Compose override and restore the previous image. Do not touch the Vaultwarden data volume.

Screenshot slot M365-S06 (pending)

Caption: Browser error response invalid_or_expired_state after a consent that was started in one browser and finished too late or elsewhere.

Provided by: Coordinator capture with an owner login.

Screenshot slot M365-S07 (pending)

Caption: Result of the lease revoke drill: the broker answers with revoked for the lease, and a following read is refused.

Provided by: Coordinator capture, only after the revoke drill has run.

Limitations​

  • No live claim. live_ready is no. Repo-ready and sandbox-evidenced is not live-ready.
  • Sandbox only. One development tenant, one owner session, one folder and one mailbox. The customer path comes with the install wizard. All four consent lanes reached active leases, but send and draft operations are not live: no draft was created, no mail was sent, and the downstream Fabric/Weft rollout remains incomplete; complete-set revocation #3711 is merged, while rollout/migration follow-up #3714 remains open (see Send and draft stages).
  • Option C residual risk. The Mail token also carries Files.Read, Mail.ReadWrite and Mail.Send (measured 2026-10-02, see above). Two Entra apps are required before the first customer tenant.
  • Admin consent differs from the old contract text. The sandbox app has admin consent for all of its listed rights, while the activation contract still records not_required.
  • Pinned redirect URI. The callback URI is a constant in the consent code and in the Keystore broker, so a different Lantern host needs a code change.
  • In-memory state. The Heddle consent state and the Lantern initiation store (single_process_ttl300) live in one process. A restart makes pending consents fail, and you start again.
  • Short windows. 300 s, 600 s, 120 s, about a minute and 900 s (see Time windows). A lease expires after 900 s unless refreshed, and a refresh was measured at about 65 s (2026-10-01) and about 95 to 100 s (2026-10-02).
  • Screenshots are placeholders. The slots above are filled by a separate capture; an Entra slot needs an owner session in the Entra portal.

Reference: activation packet (repo-only)​

The following sections keep the repo-only projection of the Universal Connections M365 activation packet. The packet is a synthetic fixture. It does not describe the live sandbox run above.

Safe starting point​

The canonical plan names delegated M365 Files, m365_file_graph, OneDrive as the primary Files profile, one opaque folder scope, and read-only access as the smallest safe start. The packet is derived from docs/plans/PLAN_UNIVERSAL_CONNECTIONS.md.

BoundaryPacket posture
Provider capabilityworkspace.file.read
Provider surfacem365_file_graph
Read scopeone_folder
Write scopenone
Graph call allowed (packet)no
Host mutation allowedno

Authority and admission chain​

The chain is server-derived and revision-bound. Platform admission does not silently enable a tenant, and tenant enablement does not grant a connection.

ReadbackCanonical reference
Fabric admissionfabric://admission/m365-file-read
Authority snapshotfabric://authority/m365-sandbox-qa
Connection revisionfabric://connection/m365-file-read/revision/1
Capability revisionfabric://capability/workspace.file.read/revision/1
Fabric authority referencekeystore://jhf-fabric/uc/authority-read-token/v1 (opaque, owner/runtime-gated; not live-read evidence)
M365 sandbox credential referencekeystore://ref/m365-sandbox-qa (generic opaque fixture reference; not the Fabric authority reference)
Opaque folder scopesandbox_required://onedrive-folder/qa-folder

Fail-closed matrix​

The packet stops on these canonical conditions:

  • scope_widening
  • permission_drift
  • authority_mismatch
  • provider_write_attempt
  • missing_ca_or_consent_evidence
  • secret_leakage
  • replay_second_provider_read

The activation contract forbids these execution classes:

  • tenant_activation_execution
  • connection_grant_execution
  • agent_tool_emission
  • provider_execution
  • customer_bundle_publication
  • certified_feed_runtime
  • beam_light_runtime
  • subscription_entitlement_truth
  • local_paid_entitlement_truth
  • trust_or_signing_key_rotation
  • security_support_until_materialization
  • production_write

Source and verification references​

  • Packet: contracts/extensions/m365_sandbox_activation_packet_v1.json
  • Readiness gate: contracts/extensions/m365_readiness_gate_v1.json
  • Permission manifest: contracts/extensions/m365_entra_permission_manifest_v1.json
  • PKCE contract: contracts/extensions/m365_delegated_authorization_code_pkce_v1.json
  • Packet schema: contracts/extensions/m365_sandbox_activation_packet_v1.schema.json
  • Activation contract: contracts/extensions/universal_connections_activation_v1_1.json
  • Runbook: docs/UNIVERSAL_CONNECTIONS_M365_SANDBOX_ACTIVATION.md
  • Plan: docs/plans/PLAN_UNIVERSAL_CONNECTIONS.md
  • Consent code: Heddle lantern_oidc_bridge/m365_consent.py
  • Initiation and handoff: Lantern bff/m365-initiation.ts, bff/m365-handoff.ts
  • Exchange and refresh: Keystore vaultwarden_oc_keystore/m365_oauth_exchange.py, docs/M365_OAUTH_EXCHANGE_RUNTIME.md
  • Verifier: scripts/verify_universal_connections_m365_sandbox_activation.py --check

This page documents a sandbox procedure. It does not activate a tenant for customers, resolve a secret, or assert live readiness.

License​

AGPLv3. Project: https://helpifyr.com