Repository navigation
Add issued API keys (gw_live_) and an AccountStore port to the open core - #12
Merged
Merged
Conversation
4 tasks
Refs #2 Co-authored-by: Colonizer Settlers <331648616+colonizer-settlers@users.noreply.github.com>
ParallelEntrepreneur
force-pushed
the
colonizer/issue-2-ecbedffe
branch
from
October 10, 2026 05:16
968dc76 to
b538bfa
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 fromcrates/ghostwritin-core/src/lib.rs: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.ApiKeyRecordholds the id, account, digest, label, a display hint and the creation time. ItsDebugoutput never prints the digest.AccountStoreport: 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 implementsApiKeys. 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 toServices::open.InMemoryAccountStore: a reference implementation for tests and local use.delete_account: removes the My voice style summary throughVoiceStore::delete, then the account and its keys. It is idempotent, so a failed deletion can be retried.StaticApiKeysand the open Worker are unchanged.Not in this PR (private crates, #10)
auth-passkeys) and the email-link fallback.AccountStore, and wiringIssuedApiKeysinto the hosted Worker'sServices.Verification
Inline unit tests cover:
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 anIssuedApiKeysrow. 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