KDCube
← Engineering
KDCube Engineering · Concept

Connection Hub Storage: Tokens, Edges, and the Line Between Them

No magic token table: handles, secrets, metadata, edges, and sessions each live where their lifecycle fits. The storage model is the design.

16 July 2026Engineering11 minConceptPunch Card
Connection Hubtoken storageidentity edgesdelegated credentialsConnectionStoreTelegram linkGrantStoreuser-scoped secrets

Connection Hub exists because integration authority arrives from several directions. A browser user signs in through platform authority. An external tool such as Claude Code asks for delegated access to a KDCube resource. A KDCube app connects to a user's Gmail, Slack, or custom OAuth account. A Telegram Mini App proves a channel actor and then asks the platform user to attach that actor to the platform account.

Those journeys should not share one storage bucket. The records look related because all of them answer "who may act?", but they answer it at different boundaries.

THE FILING RULE

Different authority facts live in different places because they have different lifecycles: delegated access is a server-side grant behind an opaque handle; connected provider accounts split metadata from raw credentials; a Telegram link is an identity edge; deployment secrets remain deployment secrets. The storage model is the design.

the.archive.mapMAP
descriptors + secrets          authority/provider policy   → deployment plane
Redis grant/session stores     delegated credentials,      → delegated-by-KDCube
                               opaque handles
ConnectionStore metadata       connected provider          → delegated-to
                               accounts                      provider account
Connection edge store          linked identities           → identity projection
                               and challenges                telegram → platform

This article is the storage map. It complements the broader Connection Hub architecture article by showing where the bytes and authority records live, why that split exists, and which record to inspect when a link, token, or delegated client does not behave as expected.

One terminology note: current routes and code still use bundle_id, bundles.yaml, and /api/integrations/bundles/.... In product prose, the deployable unit is an app. Literal identifiers keep their historical names.

01 The four records people confuse

The quickest way to debug Connection Hub is to name the record before looking for it.

QuestionRecordStorage owner
"Claude Code got an OAuth token. Where is it?"Delegated OAuth grant/session behind an opaque bearerRedis GrantStore plus delegated session authority
"I created a manual Delegated by KDCube token. Where is it?"Delegated access grant/session behind an opaque bearerSame delegated credential authority as OAuth, displayed once to the user
"A user connected Gmail or another provider. Where are those provider tokens?"Connected account metadata plus raw provider token secretConnectionStore metadata + user-scoped secrets
"A Telegram user linked to a platform user. Where is that link?"Connection Hub identity edgeConnection edge store; JSON-backed today

The first two are inbound delegated access. They let an external actor call KDCube. The third is outbound provider access. It lets KDCube call another provider for a user. The fourth is neither a token nor a provider account. It is a relationship between two independently proven identities.

02 Delegated by KDCube: the token is a handle

For delegated OAuth, an external client discovers a protected KDCube resource, registers or identifies itself, sends the user through the authorization flow, and exchanges a code for a bearer. Claude Code follows this shape when it uses Connection Hub as an OAuth authorization server for a protected MCP surface.

delegated.oauthJOURNEY
external MCP client
  → protected resource metadata
  → authorize user and collect consent
  → token endpoint returns bearer handle
  → later request: Authorization: Bearer <opaque handle>
  → managed guard hashes handle
  → loads server-side grant and session
  → checks resource, tool, grants, expiry, revocation
  → projects delegate actor + approving platform user

The bearer string is not the authority model. It is a handle into server-side state. The server-side record carries the resource grants, selected operations or tools, grantor identity, delegate identity, identity scope, expiry, and revocation state.

handle.vs.recordSPLIT
Bearer token bytes
  displayed to client
  sent over Authorization header
  never treated as the source of policy

Server-side grant/session
  selected resources
  selected tools/operations
  resource grants
  grantor platform user
  delegate actor
  expiry + revocation

Manual "Delegated by KDCube" access uses the same principle. The UI may show the generated token once because the user must copy it to an external script or tool. After that, listings expose metadata such as label, status, expiry, and last-four style hints. They do not need to expose raw bearer bytes again. The runtime validates the presented bearer by resolving the corresponding server-side grant and session.

DELEGATED BY KDCUBE · A HANDLE, NOT POLICYexternal clientClaude Code · a script · CIBearer <opaque handle>SHOWN ONCE · SENT ON EVERY CALLNEVER THE SOURCE OF POLICYConnection Hubhashes the handle · resolves the recordGRANT/SESSION DRAWERselected resourcesselected tools / operationsresource grantsgrantor platform userdelegate actoridentity scopeexpiry · revocation stateREDIS GRANTSTORE + DELEGATED SESSION AUTHORITYREVOKE THE DRAWER AND THE HANDLE STOPS RESOLVING
Fig. 1 — the bearer is a handle into the drawer; the drawer holds the policy.

03 Connected provider accounts: metadata is not credential material

When KDCube is delegated to a provider account, the storage is different. The user is not giving an external client a KDCube bearer. The user is giving KDCube a provider credential so an app, tool, or named service can call that provider.

ConnectionStore owns the metadata surface:

connection.storePATHS
<app_storage_root>/connections/<safe_user_id>/accounts.json
<app_storage_root>/connections/_oauth_states/<sha256(state)>.json

That metadata can contain provider id, account id, display name, provider subject, approved claims, credential health, and has_token. It is not the raw provider token store.

Raw provider access/refresh tokens, app passwords, and equivalent credential bytes live in user-scoped secrets. By default, Connection Hub stores them in shared user scope so another app acting for the same platform user can resolve the account through the broker without copying token bytes into its own app storage.

two.drawersSPLIT
connected account metadata
  accounts.json
  provider, account_id, label, claims, health, has_token

provider credential bytes
  user-scoped secret
  connections.accounts.<safe_account_id>.tokens

This split lets the UI say "Gmail is connected and has gmail:send" without placing Gmail tokens in the UI payload, the app descriptor, the agent prompt, or the connected-account metadata file.

CONNECTED ACCOUNT · METADATA DRAWER, SECRET DRAWERCONNECTIONSTORE · accounts.jsonprovider · account_id · labelprovider subject · approved claimscredential health · has_tokenSAYS A TOKEN EXISTS · HOLDS NO TOKENUSER-SCOPED SECRETconnections.accounts. <safe_account_id>.tokensaccess / refresh token bytesserver-side resolvertrusted SDK · broker onlyUI: “Gmail connected · gmail:send”your app · tool · named servicecalls the provider through the broker,never holding the bytesNO BROWSER / MODEL PATHTO THE SECRET DRAWERMETADATA FOR THE UI · BYTES FOR THE BROKER · NEVER THE SAME DRAWER
Fig. 2 — the metadata drawer may say a token exists; only the secret drawer holds its bytes.

04 Telegram linking is an edge, not a session

Telegram linking is the record most easily mistaken for authentication state. The Telegram Mini App proves a Telegram actor with initData; the browser proves the platform user with the normal KDCube session; Connection Hub writes an edge only after the user explicitly approves the relationship and selected grants.

link.journeyJOURNEY
Telegram Mini App
  proves telegram:<telegram_user_id>
        ↓
pending provider-claim challenge
        ↓
KDCube browser session
  proves platform:<platform_user_id>
        ↓
user selects grants and confirms
        ↓
connection edge:
  telegram.kdcube_ref:<telegram_user_id>platform:<platform_user_id>

Current implementation stores the temporary challenge and final edge in the Connection Hub app's storage:

edge.pathsPATHS
<connection-hub app storage>/connections/connection-edge-challenges.json
<connection-hub app storage>/connections/connection-edges.json

The final edge is conceptually:

connection_hub.edge.v1JSON
{{
  "schema": "connection_hub.edge.v1",
  "relationship": "delegates_to",
  "from": {{
    "authority_id": "telegram.kdcube_ref",
    "provider": "telegram",
    "subject": "100200300",
    "user_id": "telegram_100200300"
  }},
  "to": {{
    "authority_id": "platform",
    "provider": "platform",
    "subject": "02e53484-...",
    "user_id": "02e53484-..."
  }},
  "grants": [
    "identity:family",
    "economics:platform-user"
  ],
  "proof": {{ "challenge_id": "..." }},
  "metadata": {{
    "source": "telegram_miniapp",
    "telegram": {{ "id": "100200300", "username": "..." }}
  }}
}}

The edge does not make Telegram become the platform browser session. The actor for Telegram-originated work remains Telegram. The edge gives a platform boundary a way to ask: "does this Telegram actor have an approved projection to this platform subject, and which grants may cross?" That is why the grants matter:

GrantWhat it enables
identity:familyIdentity-family reads can include runtime identities connected through this edge.
economics:platform-userEconomics can evaluate spend against the linked platform user.
kdcube:role:* or permission grantsA boundary can project only roles or permissions explicitly allowed by the edge and currently held by the platform identity.

Without the edge, Telegram is still externally authenticated by Telegram proof, but it is not a platform user. Without the selected grant, the edge may exist but not satisfy the boundary that wants platform authority, economics authority, or a specific role projection.

TELEGRAM LINK · AN EDGE, NOT A SESSIONTelegram actorproven by initDatatelegram:100200300platform userproven by the browser sessionplatform:02e53484-…the connection edgedelegates_to · approved by the usergrants: identity:family · economics:platform-userPENDINGconnection-edge-challenges.jsonCOMPLETEconnection-edges.jsonschema: connection_hub.edge.v1actor · provenance stay Telegramprojection crosses by grant onlyNO EDGE → NO PLATFORM PROJECTION · NO GRANT → THAT BOUNDARY STAYS CLOSED
Fig. 3 — the edge is a filed relationship; only its selected grants cross.

05 One storage surface per lifecycle

The storage split gives each revocation and refresh operation a precise target.

RecordCurrent storageSensitive bytes?Typical revoke/repair
Authority provider configApp descriptors and platform configurationSecret refs onlyUpdate descriptor/config; rotate referenced secret separately
Deployment OAuth/client secretsPlatform secrets lifecycleYesRotate platform secret
Delegated OAuth code/CSRF/access grantRedis GrantStore keysYes, auth stateExpire/revoke grant; fail closed on missing record
Delegated bearer sessionRedis app-session authorityYes, session stateInvalidate session or let TTL expire
Manual delegated tokenOpaque handle plus server-side delegated recordRaw handle shown onceRevoke delegated access record
Connected account metadataConnectionStore account JSONNo raw provider tokenDisconnect account or change approved claims
Connected account provider tokenUser-scoped secretsYesDelete/rotate user secret; reconnect provider
Telegram/platform link challengeConnection edge challenge storeNo provider tokenExpire or complete challenge
Telegram/platform linkConnection edge storeNo provider tokenRemove edge

This is intentionally not "everything in Postgres" yet. The current reference implementation keeps connection edges JSON-backed behind the ConnectionEdgeStore contract. The important contract is the edge shape and API semantics, not the file. A production storage backend can move the edge and challenge records to a database without changing what an app asks Connection Hub to resolve.

06 What to inspect when something breaks

Debugging is faster when the failure is mapped to the right record.

triage.cardsINSPECTION
OAuth client receives bearer, but MCP call is denied
  inspect delegated grant/session:
    resource match · selected tool or operation · grant list · expiry/revocation

Connected Gmail tool says consent is missing
  inspect connected account metadata:
    account exists · approved claims cover the tool · has_token and health
  then inspect user-scoped secret only from server-side tooling

Telegram Mini App says linked=false
  inspect connection edge:
    from provider=telegram · from subject=<telegram_user_id>
    to authority=platform · status active/linked

Telegram automation runs as registered but not privileged
  inspect selected edge grants and the current platform roles
  the edge cannot project roles the platform identity does not hold
  and cannot project roles not allowed by the edge

The pattern is consistent: the proof that entered the system is not the authority by itself. The runtime validates proof, resolves the relevant Connection Hub record, intersects that record with current platform/provider state, and carries the projection only to the boundary that asked for it.

07 Why the boundary matters

Putting every credential-like object into one table would make the system harder to reason about: a delegated bearer would look like a provider account token; a Telegram identity edge would look like a platform login session; a provider refresh token would look like a resource grant; a copied secret would become the accidental source of authority.

ONE DRAWER EACH

Connection Hub separates handles, secrets, metadata, edges, and sessions. Each surface has one owner, one revocation path, and one boundary where it is allowed to project authority.

The result is boring in the best engineering sense. A bearer token is a handle. A connected account is metadata plus a user secret. A Telegram link is an edge. A platform session is platform authority. Product code can then ask Connection Hub for the projection it needs instead of becoming a private credential store.

Implementation paths to inspect when working in the platform tree: the edge store and the Connection Hub app entrypoint.

· Related articles

· Documentation on GitHub

KDCube Engineering
№ 2026-07-16 · kdcube.tech