Settings scope — instance credentials vs the person's own account

Maintainer, 2026-10-18: "double check instance settings vs user settings … apple maps key and alike must go to instance settings. user should just set up his apple account. pls revisit all settings tabs."

The rule

Home Address Holds
Instance settings Administration app (/Admin/Settings/...), platform admins only developer and platform credentials and integration configuration: Apple MapKit / WeatherKit / MusicKit keys, Google Maps key, the Google OAuth client, sign-in provider clients, model-provider keys the instance pays for, storage bindings, payments, system mail
User settings the person app (/{user}/Settings/...) what is the person's own: profile, language and time zone, notifications, launcher, their own account connections (an Apple ID, a Google or Microsoft consent, a Home Assistant they run), their personal preferences

A person is never asked to paste a developer API key to use an app. A credential bound to a user token (a Google refresh token, an Apple Music User Token) stays valid only with the developer credential that minted it; so where a person already holds such a token with their own key, that setup keeps working (see "Migration" below).

Instance keys are written to Key Vault through a SetSecrets instance action (never to node content) and reach the portal as configuration. 🚨 A value is read only when the deployment record declares its config key; the Administration tab's Value column says what the portal reads.

Inventory — the person app (`/

Read from the running company instance (first paint of rbuergi/Settings) and from the sources.

Tab id Where it shows Stores, and where Who writes Verdict
Profile user profile fields on the user node the person correct
Account user read-only: who the session is n/a correct
Preferences user language, time zone, theme on the user node the person correct
Mail user the person's Microsoft 365 mailbox consent / mail preferences the person correct (delegated consent; the app registration is instance configuration)
Inbox copies user opt-in switch per live source; copies in the person's space the person correct
Notifications user per-app notification preferences the person correct
API tokens user the person's own tokens the person correct
Security user approval step-up methods the person correct
Connected instances user the person's links to other instances the person correct
Sharing user access control on the person's partition root the person correct
Extensions user which in-app extensions the plan covers the person correct
Connections › Accounts user one row per provider; state read from the person's own records the person correct (rows link to the package tabs below)
Connections › Messaging user which channels reach the person (Teams, WhatsApp, iMessage) the person correct (bot / Business API registration is instance configuration, ConfiguredByDeployment)
Connections › MCP clients user connecting an MCP client the person correct
Connections › Signing authority user the person's signing identity and the provider they connected ({user}/_Signature/*) the person correct, see judgement call 1
Connections › Apple Music user, only where the package is held the person's Music User Token (own Apple sign-in) the person split: developer key to Administration › Integrations (was a per-user paste form)
Connections › Apple Weather user, only where the package is held pinned places and language; was also the WeatherKit key the person split: WeatherKit key to Administration › Integrations; places stay
Connections › Google user, only where the package is held the person's consent (refresh token); was also the OAuth client id and secret the person split: OAuth client to Administration › Integrations; consent stays
Connections › iCloud user, only where the package is held Apple ID + app-specific password (the person's own CalDAV credential) the person correct: an app-specific password is the person's own and no developer programme is involved
Connections › Home Assistant user, only where the package is held base URL + long-lived token of the person's own home server the person correct
Storage user (partition root) storage binding for the person's own partition ({user}/_Storage) whoever holds Update on the root correct; the instance default is the Administration › Storage tab
Threads › Settings › Models / Harnesses / Web search the AI app the person's own model-provider keys, harness logins, search default the person correct as an OPTIONAL bring-your-own key; the instance keys are Administration › AI providers (judgement call 2)
Apple Maps (MyMaps) the package page previously the person's MapKit key n/a moved already (Plugins#3321): instance key only; a stored legacy key is no longer read under Home:AppSource=Directory and says so

Inventory — the Admin app (/Admin/Settings)

Tab id Group Stores Verdict
Overview read-only build and plugin facts correct
Manage apps the apps on the instance, audience on {app}/_Policy correct
Maps Google Maps API key, Apple MapKit JS token and Server API trio (Key Vault) correct
Integrations (new) Apple WeatherKit key, Apple MusicKit key, Google OAuth client (Key Vault) correct, added by this change
AI providers shared model-provider keys and tiers correct
Administrators, Sign-in providers, Invitations, Privacy, Published to the web, Service identities People and sign-in platform access and sign-in clients correct
Updates, Operations packages, Instance registration, Fleet console, Build queue, Data sources, Governed activities, Partitions, Storage, Inbox Operations platform operations and bindings correct
Coupons, Instance grants, Composition, AI usage and cost Commercial plans, grants, cost correct

Satellite repos (read only): MeshWeaver.SocialMedia LinkedIn publishing reads its OAuth client from deployment configuration (Social:LinkedIn:ClientId / ClientSecret) and the person only connects their own account, which is already the right split. X and YouTube import the person's own archive and need no credential. Crm, Education, FundReporting, Manufacturing and Reinsurance carry no settings tab of this kind.

What this change moved

Credential Was Now Config keys
Apple WeatherKit (team, key, services id, .p8) per person ({user}/_Connections/weather) instance; the person keeps places and language AppleWeather:TeamId, :KeyId, :ServiceId, :PrivateKey
Apple MusicKit (team, key, .p8) per person (developer token minted from their key) instance; the person keeps only their Music User Token AppleMusic:TeamId, :KeyId, :PrivateKey
Google OAuth client (id, secret) per person instance; the person keeps only their consent Google:OAuth:ClientId, :ClientSecret, :RedirectUri (the authorize page URL registered on the client)

The three live as rows of Administration › Integrations (Store/AdminTabs/Integrations, area AdminIntegrations, InstanceIntegrations in Store/Catalog/Source), write-only like the Maps tab.

Migration — an already-configured key keeps working

Judgement calls for the maintainer

  1. Signature providers. Skribble, Swisscom AIS and Swisscom Sign already fall back to the mesh's Skribble:*, Swisscom:Ais:*, Swisscom:Sign:* configuration when a person has no sign-in of their own, and DeepSign is per person only. A signature account can be the operator's contract or the person's own, so it was left a person-level connection with the instance fallback. If the operator's contract should be the norm, add the same kind of Integrations rows and drop the per-person form.
  2. Bring-your-own model keys in Threads › Settings › Models stay user-level as an optional override of the instance keys; a plan that wants "instance keys only" removes that tab.
  3. Token-bound precedence above (own key kept for an existing token) deviates from "instance first" on purpose, so no configured setup breaks. Retiring it means asking those people to reconnect once.
  4. Vault declaration. Saving a key on the Integrations tab only reaches the portal once the deployment record declares the ten keys: four AppleWeather__* (TeamId, KeyId, ServiceId, PrivateKey), three AppleMusic__* (TeamId, KeyId, PrivateKey) and three Google__OAuth__* (ClientId, ClientSecret, RedirectUri); that is a deployment-record change, not made here.