Skip to content

Add issued API keys (gw_live_) and an AccountStore port to the open core - #12

Merged
ParallelEntrepreneur merged 1 commit into
mainfrom
colonizer/issue-2-ecbedffe
Oct 10, 2026
Merged

ParallelEntrepreneur merged 1 commit into
mainfrom
colonizer/issue-2-ecbedffe

Conversation

@ParallelEntrepreneur

Copy link
Copy Markdown
Contributor

Groundwork for #2 that belongs in the open core. The maintainer agreed this split: the hosted-only parts (passkey and email-link sign-in, the dashboard and the D1-backed store) plug into these open ports from the private crates (#10). This public repo gets no passkey, dashboard or D1 code.

What changed

New module crates/ghostwritin-core/src/accounts.rs, registered and re-exported from crates/ghostwritin-core/src/lib.rs:

  • Key format: gw_live_ followed by 48 hex characters (24 bytes of entropy). The caller supplies the entropy, so the core stays I/O-free and builds for wasm32. The plaintext is returned once; only its SHA-256 digest is stored.
  • KeyId: a public id derived from the digest. The dashboard uses it to list and revoke keys. ApiKeyRecord holds the id, account, digest, label, a display hint and the creation time. Its Debug output never prints the digest.
  • AccountStore port: insert a key, look a key up by digest, list an account's keys, revoke a key (scoped to its account), and delete an account with its keys.
  • IssuedApiKeys: issues, lists and revokes keys, and implements ApiKeys. Malformed keys and keys without the prefix are rejected before the store is queried, and the digest is compared in constant time. A store failure counts as unauthorized. The hosted Worker passes it to Services::open.
  • InMemoryAccountStore: a reference implementation for tests and local use.
  • delete_account: removes the My voice style summary through VoiceStore::delete, then the account and its keys. It is idempotent, so a failed deletion can be retried.

StaticApiKeys and the open Worker are unchanged.

Not in this PR (private crates, #10)

  • Passkey sign-in (harness auth-passkeys) and the email-link fallback.
  • The dashboard UI for listing and revoking keys.
  • The D1 AccountStore, and wiring IssuedApiKeys into the hosted Worker's Services.

Verification

Inline unit tests cover:

  • issuing a key and authenticating with it;
  • rejecting malformed and wrong keys;
  • listing and revoking, scoped per account;
  • account deletion removing keys and the voice summary, including when run twice.

The workspace CI gates (fmt, clippy -D warnings, test, doc, wasm32 Worker build) still have to be run. This section will be updated with their results.

Overlap with siblings

The change touches only ghostwritin-core. The README's open-core table could later gain an IssuedApiKeys row. That edit was left out because another colony (#1) is editing README.md.

Closes #2


🤖 Generated by Colonizer in a microVM

Co-Authored-By: Colonizer Settlers 331648616+colonizer-settlers@users.noreply.github.com

Refs #2

Co-authored-by: Colonizer Settlers <331648616+colonizer-settlers@users.noreply.github.com>
@ParallelEntrepreneur
ParallelEntrepreneur merged commit bbe675a into main Oct 10, 2026
1 check passed
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.

Auth: accounts, passkeys and API keys

1 participant