gora8-signer 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -45,7 +45,22 @@ async function main() {
45
45
  break;
46
46
  }
47
47
  case "start": {
48
- const policyEngine = new PolicyEngine({ fetchMandate: () => fetchMandate(agentId, apiBase) }, auditLog);
48
+ // The local storage key (agentId, this command's positional arg —
49
+ // e.g. a slugified name chosen before gora8 ever issued a real id;
50
+ // see cli/cmd/deploy.go's initSigner()) and the id gora8's Mandate
51
+ // endpoint actually looks up by (its own database cuid) are not the
52
+ // same value and never can be: `gora8-signer init` has to run
53
+ // *before* POST /v1/agents to put wallet_address in the request
54
+ // body, so at init time gora8's real id doesn't exist yet. Nothing
55
+ // in the wire protocol between gora8's API and this signer ever
56
+ // carries that real id either (requestAgentSignature's payload is
57
+ // just {operation, params}) — so without this, `start` would fetch
58
+ // /v1/agents/<local-slug>/mandate, always 404, and every signature
59
+ // would be refused forever. GORA8_AGENT_ID is the one place that
60
+ // real id is threaded through, set by whatever printed this
61
+ // command's invocation (deploy.go) once registration returns it.
62
+ const mandateAgentId = process.env.GORA8_AGENT_ID || agentId;
63
+ const policyEngine = new PolicyEngine({ fetchMandate: () => fetchMandate(mandateAgentId, apiBase) }, auditLog);
49
64
  const signer = new Signer({
50
65
  keyStore,
51
66
  policyEngine,
package/dist/keystore.js CHANGED
@@ -27,8 +27,15 @@ export class OsKeychainStore {
27
27
  async hasKey() {
28
28
  try {
29
29
  const entry = await this.entry();
30
- entry.getPassword();
31
- return true;
30
+ // @napi-rs/keyring's getPassword() returns null for a missing entry
31
+ // rather than throwing — treating "didn't throw" as "key exists"
32
+ // (the previous implementation here) is a false positive on every
33
+ // backend that behaves this way: hasKey() would report true for an
34
+ // agent that has never had a key generated, and the subsequent
35
+ // withPrivateKey()/address() call would then try to derive an
36
+ // address from null and crash. A missing entry is only genuinely
37
+ // "no key" when the returned password is a non-empty string.
38
+ return typeof entry.getPassword() === "string";
32
39
  }
33
40
  catch {
34
41
  return false;
@@ -47,6 +54,9 @@ export class OsKeychainStore {
47
54
  async withPrivateKey(fn) {
48
55
  const entry = await this.entry();
49
56
  const privateKey = entry.getPassword();
57
+ if (typeof privateKey !== "string") {
58
+ throw new Error(`No key found for agent "${this.account}" in the OS keychain — run \`gora8-signer init\` first.`);
59
+ }
50
60
  return fn(privateKey);
51
61
  }
52
62
  async address() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gora8-signer",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Local, self-custodied key signing for gora8 agents — the key is generated and used wherever your agent runs, never inside gora8's own infrastructure. See SELF_CUSTODY_ARCHITECTURE.md in the gora8 monorepo for the full design.",
5
5
  "license": "MIT",
6
6
  "type": "module",