@inneranimalmedia/agentsam-sdk 2.6.3 → 2.6.4

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.
Files changed (233) hide show
  1. package/AGENTSAM.md +6 -0
  2. package/README.md +16 -1
  3. package/bin/agentsam +16 -1
  4. package/docs/BRAND_INTELLIGENCE.md +1 -1
  5. package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
  6. package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
  7. package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  8. package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
  9. package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
  10. package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
  11. package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
  12. package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
  13. package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
  14. package/docs/architecture/SAM_KERNEL.md +181 -0
  15. package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
  16. package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
  17. package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
  18. package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
  19. package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
  20. package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
  21. package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
  22. package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
  23. package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
  24. package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
  25. package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
  26. package/migrations/d1/0013_identity_oauth_states.sql +15 -0
  27. package/migrations/d1/0014_auth_event_log.sql +20 -0
  28. package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
  29. package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
  30. package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
  31. package/package.json +19 -4
  32. package/packages/agentsam-contracts/src/errors.ts +16 -0
  33. package/packages/agentsam-errors/src/envelope.js +53 -0
  34. package/packages/agentsam-errors/src/index.js +1 -0
  35. package/packages/agentsam-errors/src/recovery.js +301 -0
  36. package/packages/agentsam-knowledge/src/providers/index.js +18 -6
  37. package/packages/connectors/cloudflare/src/routes.js +9 -0
  38. package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -1
  39. package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
  40. package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +11 -2
  41. package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
  42. package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
  43. package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
  44. package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
  45. package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
  46. package/packages/identity/package.json +2 -2
  47. package/packages/identity/src/adapters/cloudflare-d1/index.js +122 -22
  48. package/packages/identity/src/adapters/sqlite/index.js +319 -0
  49. package/packages/identity/src/app/verify-app.js +95 -0
  50. package/packages/identity/src/contracts/identity-store.js +115 -0
  51. package/packages/identity/src/contracts/route-ids.js +30 -0
  52. package/packages/identity/src/contracts/route-projection.js +218 -0
  53. package/packages/identity/src/contracts/routes.js +11 -0
  54. package/packages/identity/src/core/browser-paths.js +4 -5
  55. package/packages/identity/src/core/constants.js +13 -8
  56. package/packages/identity/src/core/session-policy.js +32 -0
  57. package/packages/identity/src/frontend/auth-portal/pages/login.html +10 -10
  58. package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
  59. package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
  60. package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
  61. package/packages/identity/src/index.js +25 -0
  62. package/packages/identity/src/oauth/README.md +10 -4
  63. package/packages/identity/src/oauth/credentials.js +20 -13
  64. package/packages/identity/src/oauth/finalize-inbound.js +1 -1
  65. package/packages/identity/src/oauth/iam-platform.js +8 -7
  66. package/packages/identity/src/oauth/redirect-paths.js +27 -36
  67. package/packages/identity/src/server/identity-service.js +30 -13
  68. package/packages/identity/src/server/mount-policy.js +30 -0
  69. package/packages/identity/src/server/post-auth.js +79 -0
  70. package/packages/identity/src/server/worker-router.js +104 -72
  71. package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
  72. package/packages/identity/tests/iam-provider.test.mjs +1 -1
  73. package/packages/identity/tests/identity-service.test.mjs +36 -5
  74. package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
  75. package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
  76. package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
  77. package/packages/theme-church-site/package.json +2 -1
  78. package/packages/theme-church-site/src/index.js +1 -0
  79. package/packages/theme-companions-site/package.json +2 -1
  80. package/packages/theme-companions-site/src/index.js +1 -0
  81. package/packages/theme-floors-site/package.json +2 -1
  82. package/packages/theme-floors-site/src/index.js +1 -0
  83. package/packages/theme-fuelnfree-site/package.json +2 -1
  84. package/packages/theme-fuelnfree-site/src/index.js +1 -0
  85. package/packages/theme-handyman-site/package.json +2 -1
  86. package/packages/theme-handyman-site/src/index.js +1 -0
  87. package/packages/theme-insurance-site/package.json +2 -1
  88. package/packages/theme-insurance-site/src/index.js +1 -0
  89. package/packages/theme-shinshu-site/package.json +2 -1
  90. package/packages/theme-shinshu-site/src/index.js +1 -0
  91. package/protocol/apps/agentsam.app.v1.schema.json +51 -0
  92. package/protocol/brand/brandpack.v1.schema.json +43 -0
  93. package/protocol/credentials/issue.v1.schema.json +38 -0
  94. package/protocol/database/connection.v1.schema.json +41 -0
  95. package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
  96. package/protocol/errors/error-envelope.schema.json +135 -1
  97. package/protocol/errors/recovery.v1.schema.json +50 -0
  98. package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
  99. package/protocol/sam/activity.v1.schema.json +48 -0
  100. package/protocol/sam/answer.v1.schema.json +35 -0
  101. package/protocol/sam/calibration.v1.schema.json +21 -0
  102. package/protocol/sam/decision-receipt.v1.schema.json +29 -0
  103. package/protocol/sam/evaluation.v1.schema.json +19 -0
  104. package/protocol/sam/operation.schema.json +66 -0
  105. package/protocol/sam/outcome.v1.schema.json +36 -0
  106. package/protocol/sam/question.v1.schema.json +26 -0
  107. package/protocol/sam/registry.seed.json +153 -0
  108. package/protocol/sam/result.schema.json +53 -0
  109. package/protocol/sam/state.v1.schema.json +23 -0
  110. package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
  111. package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
  112. package/protocol/ui/icon-registry.mjs +226 -0
  113. package/protocol/ui/icon.v1.schema.json +51 -0
  114. package/skills/README.md +22 -9
  115. package/skills/agentsam-codebaseindex/SKILL.md +225 -0
  116. package/skills/catalog.json +14 -0
  117. package/src/cli/command-catalog.js +130 -0
  118. package/src/cli/dispatch.js +48 -0
  119. package/src/cli.js +43 -1
  120. package/src/commands/api-key.js +244 -0
  121. package/src/commands/app.js +60 -28
  122. package/src/commands/brand.js +17 -19
  123. package/src/commands/codebaseindex.js +688 -0
  124. package/src/commands/env.js +152 -25
  125. package/src/commands/go.js +366 -53
  126. package/src/commands/interaction-clack.js +115 -0
  127. package/src/commands/models.js +1 -1
  128. package/src/commands/providers.js +62 -14
  129. package/src/commands/shell.js +43 -2
  130. package/src/commands/skill.js +248 -0
  131. package/src/commands/skills.js +1 -1
  132. package/src/commands/start-local.js +4 -0
  133. package/src/commands/whoami.js +90 -18
  134. package/src/go/build.js +229 -39
  135. package/src/go/cloudflare.js +506 -105
  136. package/src/go/container.js +120 -0
  137. package/src/go/contract.js +9 -4
  138. package/src/go/discover.js +149 -33
  139. package/src/go/index.js +15 -3
  140. package/src/go/native-probe-runner.mjs +119 -0
  141. package/src/go/{registry.js → official-registry.js} +64 -7
  142. package/src/go/official-release.js +10 -0
  143. package/src/go/receipts.js +77 -10
  144. package/src/go/verify.js +9 -2
  145. package/src/index.js +27 -0
  146. package/src/indexing/ingest/discover-models.js +298 -0
  147. package/src/indexing/ingest/inventory.js +243 -0
  148. package/src/indexing/ingest/job-graph.js +181 -0
  149. package/src/indexing/ingest/materials.js +210 -0
  150. package/src/lib/provider-credentials.js +63 -21
  151. package/src/lib/slash-commands.js +1 -0
  152. package/src/local-fs/capability.js +121 -0
  153. package/src/local-fs/freshness.js +75 -0
  154. package/src/local-fs/index.js +385 -0
  155. package/src/local-fs/paths.js +100 -0
  156. package/src/local-pty/server.js +295 -19
  157. package/src/mcp/client.js +2 -2
  158. package/src/models/ai-access-onboarding.js +112 -0
  159. package/src/models/discovery.js +10 -2
  160. package/src/models/inventory-core.js +9 -1
  161. package/src/sam/activity/index.js +183 -0
  162. package/src/sam/client.js +252 -0
  163. package/src/sam/decision/calibration.js +109 -0
  164. package/src/sam/decision/confidence.js +126 -0
  165. package/src/sam/decision/evaluate.js +157 -0
  166. package/src/sam/decision/evaluators/deterministic.js +341 -0
  167. package/src/sam/decision/evaluators/heuristic.js +61 -0
  168. package/src/sam/decision/evaluators/select.js +50 -0
  169. package/src/sam/decision/evaluators/semantic.js +149 -0
  170. package/src/sam/decision/hierarchical.js +61 -0
  171. package/src/sam/decision/index.js +53 -0
  172. package/src/sam/decision/policy.js +86 -0
  173. package/src/sam/decision/questions.js +120 -0
  174. package/src/sam/decision/receipt.js +148 -0
  175. package/src/sam/decision/state.js +117 -0
  176. package/src/sam/decision/types.js +22 -0
  177. package/src/sam/decision/validate.js +200 -0
  178. package/src/sam/define.js +51 -0
  179. package/src/sam/index.js +65 -0
  180. package/src/sam/operations/brand-scan.js +62 -0
  181. package/src/sam/operations/cad-blender-inspect.js +36 -0
  182. package/src/sam/operations/codebaseindex-ingest.js +49 -0
  183. package/src/sam/operations/decision-evaluate.js +59 -0
  184. package/src/sam/operations/planning-astar.js +77 -0
  185. package/src/sam/operations/planning-goap.js +60 -0
  186. package/src/sam/operations/repository-inspect.js +72 -0
  187. package/src/sam/operations/security-scan.js +33 -0
  188. package/src/sam/operations/terminal-exec.js +29 -0
  189. package/src/sam/planning/astar.js +311 -0
  190. package/src/sam/planning/goap.js +177 -0
  191. package/src/sam/planning/index.js +21 -0
  192. package/src/sam/planning/state.js +84 -0
  193. package/src/sam/registry.js +48 -0
  194. package/src/sam/result.js +77 -0
  195. package/src/sam/seed.js +44 -0
  196. package/src/sam/types.js +91 -0
  197. package/src/skills/catalog.js +64 -0
  198. package/src/skills/content-resolver.js +124 -0
  199. package/src/skills/hosted-store.js +37 -0
  200. package/src/skills/index.js +29 -64
  201. package/src/skills/interaction.js +102 -0
  202. package/src/skills/local-store.js +228 -0
  203. package/src/skills/manifest.js +104 -0
  204. package/src/skills/metrics.js +31 -0
  205. package/src/skills/registry.js +184 -0
  206. package/src/skills/runtime.js +287 -0
  207. package/src/skills/slash.js +44 -0
  208. package/src/ui/cli/help.js +94 -101
  209. package/test/cli/api-key-env-whoami.test.mjs +129 -0
  210. package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
  211. package/test/cli/go.test.mjs +62 -5
  212. package/test/cli/skill-npm-and-env.test.mjs +52 -0
  213. package/test/cli/wireframes-go-registry.test.mjs +87 -2
  214. package/test/go/build-source-identity.test.mjs +31 -0
  215. package/test/go/cloudflare-probe.test.mjs +274 -10
  216. package/test/go/distribution.test.mjs +28 -0
  217. package/test/integration/ai-access-onboarding.test.mjs +47 -0
  218. package/test/integration/cli-help.test.mjs +1 -1
  219. package/test/integration/cms-site-tenancy-contract.test.mjs +6 -6
  220. package/test/integration/codebaseindex-ingest.test.mjs +166 -0
  221. package/test/integration/icon-registry.test.mjs +67 -0
  222. package/test/integration/ingest-discover-models.test.mjs +30 -0
  223. package/test/integration/install-script.test.mjs +12 -9
  224. package/test/integration/local-fs.test.mjs +113 -0
  225. package/test/integration/provider-env-cli.test.mjs +2 -1
  226. package/test/integration/sam-activity-recovery.test.mjs +147 -0
  227. package/test/integration/sam-decision.test.mjs +584 -0
  228. package/test/integration/sam-kernel.test.mjs +99 -0
  229. package/test/integration/sam-planning-astar.test.mjs +279 -0
  230. package/test/integration/skill-runtime.test.mjs +240 -0
  231. package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
  232. package/test/models.test.mjs +14 -7
  233. package/test/shell.test.mjs +4 -4
@@ -0,0 +1,99 @@
1
+ -- identity.core — portable local SQLite (no Cloudflare / IAM required)
2
+ -- Timestamps: INTEGER unixepoch seconds
3
+
4
+ PRAGMA foreign_keys = ON;
5
+
6
+ CREATE TABLE IF NOT EXISTS identity_schema_meta (
7
+ key TEXT PRIMARY KEY NOT NULL,
8
+ value TEXT NOT NULL
9
+ );
10
+
11
+ INSERT OR REPLACE INTO identity_schema_meta (key, value)
12
+ VALUES ('schema_version', '1');
13
+
14
+ INSERT OR IGNORE INTO identity_schema_meta (key, value)
15
+ VALUES ('pack_core', '1');
16
+
17
+ CREATE TABLE IF NOT EXISTS identity_users (
18
+ id TEXT PRIMARY KEY NOT NULL,
19
+ email TEXT NOT NULL COLLATE NOCASE,
20
+ display_name TEXT,
21
+ password_hash TEXT,
22
+ salt TEXT,
23
+ status TEXT NOT NULL DEFAULT 'active',
24
+ created_at INTEGER NOT NULL,
25
+ updated_at INTEGER NOT NULL
26
+ );
27
+
28
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_identity_users_email
29
+ ON identity_users(email);
30
+
31
+ CREATE TABLE IF NOT EXISTS identity_external_accounts (
32
+ id TEXT PRIMARY KEY NOT NULL,
33
+ user_id TEXT NOT NULL,
34
+ provider TEXT NOT NULL,
35
+ provider_subject TEXT NOT NULL,
36
+ email TEXT,
37
+ created_at INTEGER NOT NULL,
38
+ updated_at INTEGER NOT NULL,
39
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
40
+ );
41
+
42
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_identity_external_provider_subject
43
+ ON identity_external_accounts(provider, provider_subject);
44
+
45
+ CREATE TABLE IF NOT EXISTS identity_sessions (
46
+ id TEXT PRIMARY KEY NOT NULL,
47
+ user_id TEXT NOT NULL,
48
+ email TEXT,
49
+ provider TEXT,
50
+ provider_subject TEXT,
51
+ display_name TEXT,
52
+ expires_at INTEGER NOT NULL,
53
+ revoked_at INTEGER,
54
+ created_at INTEGER NOT NULL,
55
+ last_active_at INTEGER,
56
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
57
+ );
58
+
59
+ CREATE INDEX IF NOT EXISTS idx_identity_sessions_user_expires
60
+ ON identity_sessions(user_id, expires_at);
61
+
62
+ CREATE TABLE IF NOT EXISTS identity_auth_events (
63
+ id TEXT PRIMARY KEY NOT NULL,
64
+ user_id TEXT,
65
+ event_type TEXT NOT NULL,
66
+ status TEXT NOT NULL DEFAULT 'ok',
67
+ provider TEXT,
68
+ metadata_json TEXT NOT NULL DEFAULT '{}',
69
+ ip_hash TEXT,
70
+ user_agent_hash TEXT,
71
+ created_at INTEGER NOT NULL DEFAULT (unixepoch())
72
+ );
73
+
74
+ CREATE INDEX IF NOT EXISTS idx_identity_auth_events_user_created
75
+ ON identity_auth_events(user_id, created_at DESC);
76
+
77
+ CREATE TABLE IF NOT EXISTS identity_app_registry (
78
+ id TEXT PRIMARY KEY NOT NULL,
79
+ package_name TEXT,
80
+ manifest_version TEXT,
81
+ display_name TEXT,
82
+ authenticated_route_id TEXT NOT NULL,
83
+ login_route_id TEXT NOT NULL,
84
+ recovery_route_id TEXT NOT NULL,
85
+ enabled INTEGER NOT NULL DEFAULT 1,
86
+ installed_at INTEGER NOT NULL,
87
+ updated_at INTEGER NOT NULL
88
+ );
89
+
90
+ CREATE TABLE IF NOT EXISTS identity_route_registry (
91
+ app_id TEXT NOT NULL,
92
+ route_id TEXT NOT NULL,
93
+ path_pattern TEXT NOT NULL,
94
+ runtime TEXT,
95
+ auth_policy TEXT,
96
+ shell_ref TEXT,
97
+ PRIMARY KEY (app_id, route_id),
98
+ FOREIGN KEY (app_id) REFERENCES identity_app_registry(id)
99
+ );
@@ -0,0 +1,38 @@
1
+ -- identity.oauth-client — outbound OAuth (sign in with Google/CF/GitHub/IAM)
2
+ -- Secrets/tokens live in the local encrypted vault; this pack stores refs + metadata.
3
+
4
+ INSERT OR IGNORE INTO identity_schema_meta (key, value)
5
+ VALUES ('pack_oauth_client', '1');
6
+
7
+ CREATE TABLE IF NOT EXISTS identity_oauth_transactions (
8
+ state TEXT PRIMARY KEY NOT NULL,
9
+ provider TEXT NOT NULL,
10
+ code_verifier TEXT NOT NULL,
11
+ return_to TEXT,
12
+ app_id TEXT NOT NULL,
13
+ expires_at INTEGER NOT NULL,
14
+ created_at INTEGER NOT NULL,
15
+ consumed_at INTEGER
16
+ );
17
+
18
+ CREATE INDEX IF NOT EXISTS idx_identity_oauth_transactions_expires
19
+ ON identity_oauth_transactions(expires_at);
20
+
21
+ CREATE INDEX IF NOT EXISTS idx_identity_oauth_transactions_app
22
+ ON identity_oauth_transactions(app_id);
23
+
24
+ CREATE TABLE IF NOT EXISTS identity_provider_connections (
25
+ id TEXT PRIMARY KEY NOT NULL,
26
+ user_id TEXT NOT NULL,
27
+ provider TEXT NOT NULL,
28
+ granted_scopes_json TEXT NOT NULL DEFAULT '[]',
29
+ credential_ref TEXT NOT NULL,
30
+ expires_at INTEGER,
31
+ refreshable INTEGER NOT NULL DEFAULT 0,
32
+ created_at INTEGER NOT NULL,
33
+ updated_at INTEGER NOT NULL,
34
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
35
+ );
36
+
37
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_identity_provider_connections_user_provider
38
+ ON identity_provider_connections(user_id, provider);
@@ -0,0 +1,64 @@
1
+ -- identity.oauth-server — OPTIONAL pack for products that issue their own
2
+ -- client IDs, authorization codes, access tokens, and refresh tokens.
3
+ -- Do not apply unless the installed product is an OAuth authorization server.
4
+
5
+ INSERT OR IGNORE INTO identity_schema_meta (key, value)
6
+ VALUES ('pack_oauth_server', '1');
7
+
8
+ CREATE TABLE IF NOT EXISTS identity_oauth_clients (
9
+ id TEXT PRIMARY KEY NOT NULL,
10
+ client_id TEXT NOT NULL UNIQUE,
11
+ client_secret_hash TEXT,
12
+ name TEXT NOT NULL,
13
+ redirect_uris_json TEXT NOT NULL DEFAULT '[]',
14
+ grant_types_json TEXT NOT NULL DEFAULT '["authorization_code"]',
15
+ token_endpoint_auth_method TEXT NOT NULL DEFAULT 'none',
16
+ created_at INTEGER NOT NULL,
17
+ updated_at INTEGER NOT NULL
18
+ );
19
+
20
+ CREATE TABLE IF NOT EXISTS identity_oauth_authorization_codes (
21
+ code_hash TEXT PRIMARY KEY NOT NULL,
22
+ client_id TEXT NOT NULL,
23
+ user_id TEXT NOT NULL,
24
+ redirect_uri TEXT NOT NULL,
25
+ scopes_json TEXT NOT NULL DEFAULT '[]',
26
+ code_challenge TEXT,
27
+ code_challenge_method TEXT,
28
+ expires_at INTEGER NOT NULL,
29
+ consumed_at INTEGER,
30
+ created_at INTEGER NOT NULL,
31
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
32
+ );
33
+
34
+ CREATE TABLE IF NOT EXISTS identity_oauth_access_tokens (
35
+ token_hash TEXT PRIMARY KEY NOT NULL,
36
+ client_id TEXT NOT NULL,
37
+ user_id TEXT NOT NULL,
38
+ scopes_json TEXT NOT NULL DEFAULT '[]',
39
+ expires_at INTEGER NOT NULL,
40
+ revoked_at INTEGER,
41
+ created_at INTEGER NOT NULL,
42
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
43
+ );
44
+
45
+ CREATE TABLE IF NOT EXISTS identity_oauth_refresh_tokens (
46
+ token_hash TEXT PRIMARY KEY NOT NULL,
47
+ client_id TEXT NOT NULL,
48
+ user_id TEXT NOT NULL,
49
+ scopes_json TEXT NOT NULL DEFAULT '[]',
50
+ expires_at INTEGER NOT NULL,
51
+ revoked_at INTEGER,
52
+ created_at INTEGER NOT NULL,
53
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
54
+ );
55
+
56
+ CREATE TABLE IF NOT EXISTS identity_oauth_grants (
57
+ id TEXT PRIMARY KEY NOT NULL,
58
+ client_id TEXT NOT NULL,
59
+ user_id TEXT NOT NULL,
60
+ scopes_json TEXT NOT NULL DEFAULT '[]',
61
+ created_at INTEGER NOT NULL,
62
+ revoked_at INTEGER,
63
+ FOREIGN KEY (user_id) REFERENCES identity_users(id)
64
+ );
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-sdk-identity",
3
- "version": "2.6.3",
3
+ "version": "2.6.4",
4
4
  "private": true,
5
5
  "type": "module",
6
- "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace \u2014 publish via root SDK)",
6
+ "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace — publish via root SDK)",
7
7
  "agentsam": {
8
8
  "system": "identity",
9
9
  "kind": "library",
@@ -1,7 +1,10 @@
1
+ import { SESSION_POLICY } from '../../core/constants.js';
2
+ import { IdentitySchemaError } from '../../contracts/identity-store.js';
3
+ import { IDENTITY_STORE_SCHEMA_VERSION } from '../../contracts/identity-store.js';
1
4
  import { newAccountIdentityId, newAuthUserId, newSessionId, newAuthEventId, nowUnix } from './ids.js';
2
- import { AUTH_SESSION_TTL_SECONDS } from '../../core/constants.js';
3
5
  import { DEFAULT_COMPANY_ID, DEFAULT_COMPANY_SLUG, normalizeCompanyRow } from '../../contracts/company.js';
4
6
 
7
+
5
8
  /**
6
9
  * @typedef {object} D1Database
7
10
  * @property {(sql: string) => { bind: (...args: unknown[]) => { first: () => Promise<unknown>, run: () => Promise<unknown>, all: () => Promise<{ results?: unknown[] }> } }} prepare
@@ -24,22 +27,45 @@ export function createCloudflareD1Adapter(db, options = {}) {
24
27
  if (!db?.prepare) {
25
28
  throw new Error('cloudflare_d1_adapter_requires_db_binding');
26
29
  }
27
- const sessionTtlSeconds = options.sessionTtlSeconds ?? AUTH_SESSION_TTL_SECONDS;
30
+ const sessionTtlSeconds = options.sessionTtlSeconds ?? SESSION_POLICY.browser.ttlSeconds;
28
31
 
29
32
  return Object.freeze({
33
+ schemaVersion: IDENTITY_STORE_SCHEMA_VERSION,
30
34
  sessionTtlSeconds,
35
+ backend: 'cloudflare-d1',
31
36
 
32
37
  /**
33
38
  * Append-only login/logout/failed-attempt audit trail (auth_event_log).
34
- * Never throws -- an observability write must not break a real auth flow.
35
- * ip/userAgent are hashed (SHA-256) before storage, matching the
36
- * ip_hash/user_agent_hash column names -- raw values are never persisted.
39
+ * Never throws — an observability write must not break a real auth flow.
40
+ * status remains the event outcome only ('ok' | 'failed').
41
+ * Richer context (session, capabilities, activity, client) goes in metadata_json.
42
+ * ip/userAgent are hashed (SHA-256) — raw values are never persisted.
37
43
  */
38
- async logAuthEvent({ userId, eventType, status = 'ok', provider, metadata, request }) {
44
+ async logAuthEvent({
45
+ userId,
46
+ accountId,
47
+ eventType,
48
+ status = 'ok',
49
+ provider,
50
+ session,
51
+ capabilities,
52
+ activity,
53
+ client,
54
+ metadata,
55
+ request,
56
+ }) {
39
57
  try {
40
58
  const ip = request?.headers?.get?.('cf-connecting-ip') || request?.headers?.get?.('x-forwarded-for') || '';
41
59
  const ua = request?.headers?.get?.('user-agent') || '';
42
60
  const [ipHash, uaHash] = await Promise.all([hashValue(ip), hashValue(ua)]);
61
+ const envelope = {
62
+ ...(metadata && typeof metadata === 'object' ? metadata : {}),
63
+ ...(accountId ? { accountId } : {}),
64
+ ...(session ? { session } : {}),
65
+ ...(capabilities ? { capabilities } : {}),
66
+ ...(activity ? { activity } : {}),
67
+ ...(client ? { client } : {}),
68
+ };
43
69
  await db.prepare(
44
70
  `INSERT INTO auth_event_log
45
71
  (id, user_id, event_type, status, provider, metadata_json, ip_hash, user_agent_hash)
@@ -50,7 +76,7 @@ export function createCloudflareD1Adapter(db, options = {}) {
50
76
  eventType,
51
77
  status,
52
78
  provider || null,
53
- metadata ? JSON.stringify(metadata) : '{}',
79
+ JSON.stringify(envelope),
54
80
  ipHash,
55
81
  uaHash,
56
82
  ).run();
@@ -59,6 +85,34 @@ export function createCloudflareD1Adapter(db, options = {}) {
59
85
  }
60
86
  },
61
87
 
88
+ /**
89
+ * Account/session activity snapshot for auth receipts (not event outcome).
90
+ * @param {string} userId
91
+ */
92
+ async countAuthActivity(userId) {
93
+ if (!userId) {
94
+ return { loginCount: 0, activeSessionCount: 0, lastLoginAt: null };
95
+ }
96
+ try {
97
+ const logins = await db.prepare(
98
+ `SELECT COUNT(*) AS c, MAX(created_at) AS last_at
99
+ FROM auth_event_log
100
+ WHERE user_id = ? AND event_type = 'login' AND status = 'ok'`,
101
+ ).bind(userId).first();
102
+ const sessions = await db.prepare(
103
+ `SELECT COUNT(*) AS c FROM auth_sessions
104
+ WHERE user_id = ? AND revoked_at IS NULL AND expires_at > ?`,
105
+ ).bind(userId, nowUnix()).first();
106
+ return {
107
+ loginCount: Number(logins?.c || 0),
108
+ activeSessionCount: Number(sessions?.c || 0),
109
+ lastLoginAt: logins?.last_at != null ? Number(logins.last_at) : null,
110
+ };
111
+ } catch {
112
+ return { loginCount: 0, activeSessionCount: 0, lastLoginAt: null };
113
+ }
114
+ },
115
+
62
116
  async findUserByEmail(email) {
63
117
  const row = await db.prepare(
64
118
  `SELECT id, email, display_name, password_hash, salt, status, created_at, updated_at
@@ -173,27 +227,73 @@ export function createCloudflareD1Adapter(db, options = {}) {
173
227
  return { ok: true, reason };
174
228
  },
175
229
 
176
- async saveOAuthState({ state, provider, codeVerifier, redirectTo, ttlSeconds = 600 }) {
177
- // Dedicated table, deliberately NOT named `oauth_states` -- that name collides
178
- // with unrelated Stripe Connect state tracking in customer apps that reuse
179
- // their inneranimalmedia D1 instance (id/user_id/provider_id/redirect_uri/
180
- // scope schema, no default on primary key). See AgentSamRemix incident,
181
- // 2026-08-29: D1_ERROR: table oauth_states has no column named state.
230
+ async createOAuthTransaction({ state, provider, codeVerifier, returnTo, redirectTo, appId, ttlSeconds = 600 }) {
231
+ if (!appId) {
232
+ throw new IdentitySchemaError(
233
+ 'OAUTH_TRANSACTION_APP_ID_REQUIRED',
234
+ 'OAuth transactions must include app_id',
235
+ );
236
+ }
182
237
  const ts = nowUnix();
183
- await db.prepare(
184
- `INSERT INTO identity_oauth_states (state, provider, code_verifier, redirect_to, expires_at, created_at)
185
- VALUES (?, ?, ?, ?, ?, ?)`,
186
- ).bind(state, provider, codeVerifier, redirectTo || null, ts + ttlSeconds, ts).run();
238
+ const expiresAt = ts + ttlSeconds;
239
+ try {
240
+ await db.prepare(
241
+ `INSERT INTO identity_oauth_states
242
+ (state, provider, code_verifier, redirect_to, app_id, expires_at, created_at)
243
+ VALUES (?, ?, ?, ?, ?, ?, ?)`,
244
+ ).bind(state, provider, codeVerifier, returnTo ?? redirectTo ?? null, appId, expiresAt, ts).run();
245
+ } catch (err) {
246
+ throw new IdentitySchemaError(
247
+ 'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
248
+ 'identity_oauth_states.app_id required — apply migration 0015 (no silent pre-app_id fallback)',
249
+ { cause: String(err?.message || err) },
250
+ );
251
+ }
187
252
  },
188
253
 
189
- async consumeOAuthState(state) {
190
- const row = await db.prepare(
191
- `SELECT state, provider, code_verifier, redirect_to, expires_at FROM identity_oauth_states WHERE state = ? LIMIT 1`,
192
- ).bind(state).first();
254
+ /** @deprecated Use createOAuthTransaction */
255
+ async saveOAuthState(input) {
256
+ return this.createOAuthTransaction(input);
257
+ },
258
+
259
+ async consumeOAuthTransaction(state) {
260
+ let row;
261
+ try {
262
+ row = await db.prepare(
263
+ `SELECT state, provider, code_verifier, redirect_to, app_id, expires_at, created_at
264
+ FROM identity_oauth_states WHERE state = ? LIMIT 1`,
265
+ ).bind(state).first();
266
+ } catch (err) {
267
+ throw new IdentitySchemaError(
268
+ 'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
269
+ 'identity_oauth_states.app_id column missing — apply migration 0015',
270
+ { cause: String(err?.message || err) },
271
+ );
272
+ }
193
273
  if (!row) return null;
194
274
  await db.prepare(`DELETE FROM identity_oauth_states WHERE state = ?`).bind(state).run();
195
275
  if (row.expires_at <= nowUnix()) return null;
196
- return row;
276
+ if (!row.app_id) {
277
+ throw new IdentitySchemaError(
278
+ 'IDENTITY_SCHEMA_MIGRATION_REQUIRED',
279
+ 'OAuth transaction missing app_id — refuse silent pre-app_id semantics',
280
+ );
281
+ }
282
+ return {
283
+ state: row.state,
284
+ provider: row.provider,
285
+ code_verifier: row.code_verifier,
286
+ redirect_to: row.redirect_to,
287
+ return_to: row.redirect_to,
288
+ app_id: row.app_id,
289
+ expires_at: row.expires_at,
290
+ created_at: row.created_at,
291
+ };
292
+ },
293
+
294
+ /** @deprecated Use consumeOAuthTransaction */
295
+ async consumeOAuthState(state) {
296
+ return this.consumeOAuthTransaction(state);
197
297
  },
198
298
 
199
299
  async getCompanyBySlug(slug = DEFAULT_COMPANY_SLUG) {