feat(appstash): shared stash identity, session fields, secret codec, atomic 0600 writes - #105
Merged
Merged
Conversation
…atomic 0600 writes
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
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.
Summary
Step 1 of consolidating our four credential stores onto one (constructive-planning#1430).
createConfigStoreis already the canonical store — the generated csdk executors use it — so this makes it capable enough that the csdk local duplicate, the agent CLI'saccount.json/backend-config.json, and the desktopAccountStorecan all become callers rather than reimplementations.One signed-in state across several binaries. Generated SDK CLIs pass their own CLI name as the tool name, which today means each one gets its own hidden dir and its own login. New
stashNameseparates where state lives from what the tool is called:toolNamestill drives theCSDK_TOKEN/CSDK_API_ENDPOINTenv prefixes and the command names ingetClientConfig's error text, so a shared dir doesn't blur the tools' identities. OmittingstashNamekeeps today's per-tool isolation.Session identity on credentials.
ContextCredentialsgainsuserId,email,apiKey,keyId,apiKeyExpiresAt,signedInAt— the fieldsStoredSessioncarries in the agent CLI and desktop today. Additive and optional.SecretCodecfor at-rest encryption. Secret-bearing fields (token,refreshToken,apiKey) pass through an optional codec on the way to disk; everything else stays readable for debugging. Desktop supplies an ElectronsafeStoragecodec and gets the same file layout as the CLI:The codec name is recorded in
credentials.json, so credentials written by a different codec are reported (sign in again to rewrite them) instead of being decoded into garbage.Durability and permissions.
writeJsonis now atomic (temp file +rename, mode applied before the rename) and defaults to0600for every file, not justcredentials.json— context files and vars can hold endpoints and secrets too.No silent swallowing.
readJsonpreviously returned the caller's fallback when a file existed but didn't parse, so a half-written or hand-edited file looked like "no config" and got overwritten;listContextsdid the same per file. Both now throwMalformed JSON in <path>. Missing files still return the fallback — absence is normal, corruption isn't.Tests:
__tests__/config-store-shared.test.ts(12 cases — shared/isolated stash, env-prefix independence, identity round-trip, codec encode/decode + mismatch + empty store, 0600 on all files, no temp leftovers, throw-on-malformed). Existing 77 appstash tests unchanged and passing; consumers (confstash,genomic,create-gen-app-test) pass.Link to Devin session: https://app.devin.ai/sessions/783ae9ff63b445879450d5051d9d3d83
Requested by: @pyramation