Skip to content

RFC: Mentra-owned developer API keys (take WorkOS out of the publish path)#3289

Closed
aisraelov wants to merge 1 commit into
devfrom
aisraelov/cloud2-api-keys-design
Closed

RFC: Mentra-owned developer API keys (take WorkOS out of the publish path)#3289
aisraelov wants to merge 1 commit into
devfrom
aisraelov/cloud2-api-keys-design

Conversation

@aisraelov

@aisraelov aisraelov commented Jun 30, 2026

Copy link
Copy Markdown
Member

Design-only RFC — no code in this PR. Companion to #3288 (console org roles).

Context

In Cloud V2 today, a developer's API key — the credential that publishes a miniapp to glasses headlessly / from CI — is a WorkOS-managed secret, created via workos().apiKeys.createOrganizationApiKey and validated on every request with a round-trip to workos().apiKeys.createValidation. WorkOS is sitting in the critical publish path, not just login.

This RFC proposes issuing + validating those keys ourselves in Core + our DB, and removing WorkOS from the publish path. Interactive mentra login stays on WorkOS.

What's in the doc

cloud-v2/docs/issues/019-developer-api-keys/README.md:

  • DeveloperOrgApiKey model in our DB — stores only sha256(secret), never the secret.
  • Env-pinned key format msk_<env>_<keyId>_<secret> — embedded keyId makes validation an indexed lookup; the env prefix hard-fails cross-environment use and eases leak triage.
  • Local validation in authenticateConsoleSession — constant-time hash compare, throttled lastUsedAt, instant revokedAt revocation, no vendor round-trip.
  • Zero-downtime dual-stack migration — accept WorkOS keys and Mentra keys during a window, nudge rotation, then delete the workos().apiKeys.* paths once telemetry shows no WorkOS-key validations.
  • Why it's low-risk for us to own: Core already mints/verifies Ed25519 miniapp tokens, manages refresh tokens, and stores signing keys — a hashed random secret is simpler than what's already there.
  • Open questions for Isaiah: hash choice (SHA-256 vs Argon2), org plumbing (map to workosOrgId vs first-class developerOrgId), per-key scopes, key branding, legacy-key handling.

Ask

Review the approach + answer the open questions. Once the direction is agreed, I'll implement Phase 2a (issuance + validation + WorkOS fallback) behind the existing API so nothing breaks.


Note

Low Risk
Documentation-only; no runtime, auth, or data-path changes until a follow-up implementation PR.

Overview
This PR only adds cloud-v2/docs/issues/019-developer-api-keys/README.md — a proposal/RFC with no implementation.

The doc spells out a planned move away from WorkOS for headless/CI console API keys (create/list/revoke via workos().apiKeys.* and per-request createValidation in authenticateApiKeyToken), while keeping WorkOS for interactive mentra login session JWTs. The intended future shape is a DeveloperOrgApiKey record (hash-only secret storage), msk_<env>_<keyId>_<secret> issuance, and authenticateMentraApiKey wired into authenticateConsoleSession for bearer tokens starting with msk_, with WorkOS keys accepted during a phased cutover.

It also captures security (constant-time compare, env pinning, revocation), org resolution (v1 maps to existing workosOrgId plumbing), phases 2a–2c, and open questions for review (hash choice, org fields, scopes, legacy key UX).

Reviewed by Cursor Bugbot for commit bc678b7. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Design-only RFC to replace WorkOS-managed org API keys with Mentra-issued keys for miniapp publishing. Moves issuance and validation into Core + our DB, keeps interactive mentra login on WorkOS, and builds on the access gates in PR #3288.

  • New Features

    • DeveloperOrgApiKey model storing only sha256(secret) plus metadata.
    • Env‑pinned key format msk_<env>_<keyId>_<secret>; keyId enables indexed lookup and targeted revocation.
    • Local validation in authenticateConsoleSession: constant‑time compare, throttled lastUsedAt, instant revokedAt.
    • Minimal v1 maps to workosOrgId; per-key scopes can follow later.
  • Migration

    • Run dual-stack: accept Mentra and WorkOS keys; CLI stays Bearer-based and unchanged.
    • Prompt rotation and optionally show legacy WorkOS keys read-only.
    • Remove workos().apiKeys.* after telemetry shows no WorkOS-key validations.

Written for commit bc678b7. Summary will update on new commits.

Review in cubic

…ish path)

Design-only proposal to issue + validate developer-console API keys in Core +
our DB, replacing WorkOS-managed org API keys (workos().apiKeys.*). WorkOS stays
for interactive login only. Covers the DeveloperOrgApiKey model, env-pinned
hashed key format, local validation, a zero-downtime dual-stack migration, and
open questions for review. Builds on the org roles gate in PR #3288.
@github-actions

Copy link
Copy Markdown
Contributor

📋 PR Review Helper

📱 Mobile App Build

Waiting for build...

🕶️ ASG Client Build

Waiting for build...


🔀 Test Locally

gh pr checkout 3289

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit bc678b7. Configure here.


- If the token starts with `msk_`, route to `authenticateMentraApiKey(token)`:
1. Parse `env`, `keyId`, `secret`. Reject if `env !== <this Core's env>`.
2. `findOne({ keyId, revokedAt: null })`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Underscore key format ambiguity

High Severity

The proposed msk_&lt;env&gt;_&lt;keyId&gt;_&lt;secret&gt; layout and step to parse env, keyId, and secret conflicts with keyId documented as dak_&lt;ulid&gt;, which adds another underscore. A naive split on _ mis-identifies keyId and secret, so validation would reject valid keys.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bc678b7. Configure here.

In `authenticateConsoleSession`, on the bearer path:

- If the token starts with `msk_`, route to `authenticateMentraApiKey(token)`:
1. Parse `env`, `keyId`, `secret`. Reject if `env !== <this Core's env>`.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Env pin omits local

Medium Severity

The key format allows only dev, staging, and prod, but Core’s consoleEnvironmentLabel() also resolves local, debug, and other values. Minted keys and validation’s env !== this Core’s env check can disagree with local or debug deployments.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit bc678b7. Configure here.

@github-actions

Copy link
Copy Markdown
Contributor

PR Agent Orchestrator State

{
  "cycle": 1,
  "fixRound": 0,
  "totalReviewerRuns": 1,
  "consecutiveNoNewReviews": 1,
  "openFindings": [],
  "resolvedFindings": [],
  "nitFindings": [],
  "phase": "discovery",
  "status": "in_progress",
  "stagnationFixRounds": 0,
  "fingerprintReopenCounts": {},
  "mutedFingerprints": [],
  "lastPair": [],
  "lastOpenCount": 0
}

@github-actions

Copy link
Copy Markdown
Contributor

🤖 PR Agent Review — cycle 1

✅ No blocking findings · 0 blocking · 0 nits
Reviewers this cycle: none

No model reviews ran this cycle.

Updated automatically by the PR Agent Orchestrator each review cycle. Nits do not block merge.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc678b776d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


1. **Add, don't replace.** Ship Mentra-key issuance + validation **while still
accepting WorkOS keys** (keep the existing fallback). New keys created in the
console are Mentra keys; the list reads from our DB.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep legacy WorkOS keys revocable during migration

During the dual-stack window, this plan keeps existing WorkOS API keys valid but makes the console list read only from the new DB; the current console token surface discovers and revokes those WorkOS keys through GET/DELETE /console/tokens in cloud-v2/packages/core/src/api/console/cli-auth.api.ts lines 671-730. If a legacy key is leaked after Phase 2a, owners would no longer have a console path to find or revoke that still-valid credential, and surfacing it only as an optional read-only badge later does not restore revocation. Please make legacy WorkOS listing/revocation part of the dual-stack phase, or stop accepting legacy keys once they are hidden.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

console are Mentra keys; the list reads from our DB.

P1 Badge Keep legacy WorkOS keys revocable during migration

During the dual-stack window, this plan keeps existing WorkOS API keys valid but makes the console list read only from the new DB; the current console token surface discovers and revokes those WorkOS keys through GET/DELETE /console/tokens in cloud-v2/packages/core/src/api/console/cli-auth.api.ts lines 671-730. If a legacy key is leaked after Phase 2a, owners would no longer have a console path to find or revoke that still-valid credential, and surfacing it only as an optional read-only badge later does not restore revocation. Please make legacy WorkOS listing/revocation part of the dual-stack phase, or stop accepting legacy keys once they are hidden.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@aisraelov aisraelov closed this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant