@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
@@ -1,7 +1,29 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { describe, it } from 'node:test';
3
+ import { IDENTITY_ROUTE_IDS } from '../src/contracts/route-ids.js';
4
+ import {
5
+ createRouteRegistry,
6
+ defineRouteProjection,
7
+ } from '../src/contracts/route-projection.js';
3
8
  import { createIdentityService } from '../src/server/identity-service.js';
4
9
 
10
+ function createTestRouting() {
11
+ const app = { id: 'identity-test-app' };
12
+ const routeRegistry = createRouteRegistry([
13
+ defineRouteProjection({
14
+ appId: app.id,
15
+ routes: {
16
+ [IDENTITY_ROUTE_IDS.LOGIN]: '/auth/login',
17
+ [IDENTITY_ROUTE_IDS.RECOVERY]: '/auth/reset',
18
+ [IDENTITY_ROUTE_IDS.APP_AUTHENTICATED]: '/agentsam',
19
+ [IDENTITY_ROUTE_IDS.OAUTH_CALLBACK]: '/api/oauth/:provider/callback',
20
+ 'app.mount./projects': { path: '/projects', auth: 'required' },
21
+ },
22
+ }),
23
+ ]);
24
+ return { app, routeRegistry };
25
+ }
26
+
5
27
  function createMemoryAdapter() {
6
28
  const users = new Map();
7
29
  const sessions = new Map();
@@ -66,10 +88,12 @@ function createMemoryAdapter() {
66
88
  }
67
89
 
68
90
  describe('identity service', () => {
69
- it('owns its fallback and rejects external OAuth return targets', () => {
91
+ it('owns its projected fallback and rejects external OAuth return targets', () => {
92
+ const { app, routeRegistry } = createTestRouting();
70
93
  const identity = createIdentityService({
71
94
  adapter: createMemoryAdapter(),
72
- defaultRedirect: '/agentsam',
95
+ app,
96
+ routeRegistry,
73
97
  });
74
98
 
75
99
  assert.equal(identity.resolvePostLoginPath('/projects?tab=recent'), '/projects?tab=recent');
@@ -77,12 +101,19 @@ describe('identity service', () => {
77
101
  assert.equal(identity.resolvePostLoginPath('//attacker.example/'), '/agentsam');
78
102
  assert.equal(identity.resolvePostLoginPath(null), '/agentsam');
79
103
 
80
- const neutral = createIdentityService({ adapter: createMemoryAdapter() });
81
- assert.equal(neutral.resolvePostLoginPath(null), '/');
104
+ assert.throws(
105
+ () => createIdentityService({ adapter: createMemoryAdapter() }),
106
+ (error) => error?.code === 'AUTH_APP_UNRESOLVED',
107
+ );
82
108
  });
83
109
 
84
110
  it('signup and login issue session', async () => {
85
- const identity = createIdentityService({ adapter: createMemoryAdapter() });
111
+ const { app, routeRegistry } = createTestRouting();
112
+ const identity = createIdentityService({
113
+ adapter: createMemoryAdapter(),
114
+ app,
115
+ routeRegistry,
116
+ });
86
117
  const signup = await identity.signup({
87
118
  email: 'user@example.com',
88
119
  password: 'secret-pass',
@@ -42,8 +42,10 @@ describe('oauth credentials', () => {
42
42
  const lane = resolveOAuthCredentialLane(env, 'google');
43
43
  assert.equal(lane?.lane, 'byok_google');
44
44
  assert.equal(lane?.clientId, 'google-byok');
45
- // IAM start path still resolves IAM
45
+ // IAM / inneranimalmedia start path still resolves platform lane
46
46
  assert.equal(resolveOAuthCredentialLane(env, 'iam')?.lane, 'iam_platform');
47
+ assert.equal(resolveOAuthCredentialLane(env, 'inneranimalmedia')?.provider, 'inneranimalmedia');
48
+ assert.equal(resolveOAuthCredentialLane(env, 'inneranimalmedia')?.lane, 'iam_platform');
47
49
  });
48
50
 
49
51
  it('prefers IAM_OAUTH_ISSUER and exposes issuer as the canonical authority', () => {
@@ -0,0 +1,157 @@
1
+ import assert from 'node:assert/strict';
2
+ import fs from 'node:fs';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { describe, it } from 'node:test';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { createLocalSqliteDatabase } from '../../../src/local/sqlite.js';
8
+ import { IDENTITY_ROUTE_IDS } from '../src/contracts/route-ids.js';
9
+ import {
10
+ createRouteRegistry,
11
+ projectionFromAppManifest,
12
+ } from '../src/contracts/route-projection.js';
13
+ import { IdentityRoutingError } from '../src/contracts/identity-store.js';
14
+ import { resolvePostAuthDestination } from '../src/server/post-auth.js';
15
+ import {
16
+ applySqliteIdentityMigrations,
17
+ createSqliteIdentityAdapter,
18
+ } from '../src/adapters/sqlite/index.js';
19
+ import { createIdentityService } from '../src/server/identity-service.js';
20
+ import { verifyAppPackage, verifyAppAuthContract } from '../src/app/verify-app.js';
21
+ import { SESSION_POLICY } from '../src/core/session-policy.js';
22
+
23
+ const REPO = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../..');
24
+ const LOCAL_STUDIO = path.join(REPO, 'apps/local-studio');
25
+
26
+ describe('IDENTITY_ROUTE_IDS (portable semantics)', () => {
27
+ it('exports semantic IDs only — no host paths', () => {
28
+ assert.equal(IDENTITY_ROUTE_IDS.LOGIN, 'identity.login');
29
+ assert.equal(IDENTITY_ROUTE_IDS.APP_AUTHENTICATED, 'app.authenticated');
30
+ assert.equal(IDENTITY_ROUTE_IDS.OAUTH_CALLBACK, 'identity.oauth.callback');
31
+ for (const v of Object.values(IDENTITY_ROUTE_IDS)) {
32
+ assert.equal(v.includes('/'), false, `path leaked into portable ID: ${v}`);
33
+ }
34
+ });
35
+ });
36
+
37
+ describe('route projection + fail-closed post-auth', () => {
38
+ const manifest = JSON.parse(
39
+ fs.readFileSync(path.join(LOCAL_STUDIO, 'agentsam.app.json'), 'utf8'),
40
+ );
41
+ const projection = projectionFromAppManifest(manifest);
42
+ const routeRegistry = createRouteRegistry([projection]);
43
+ const app = { id: 'local-studio' };
44
+
45
+ it('host projection maps identity.login → /auth/login', () => {
46
+ assert.equal(routeRegistry.resolve('local-studio', IDENTITY_ROUTE_IDS.LOGIN), '/auth/login');
47
+ assert.equal(
48
+ routeRegistry.resolve('local-studio', IDENTITY_ROUTE_IDS.APP_AUTHENTICATED),
49
+ '/agentsam',
50
+ );
51
+ });
52
+
53
+ it('resumes validated return_to', () => {
54
+ assert.equal(
55
+ resolvePostAuthDestination({
56
+ transaction: { app_id: 'local-studio', return_to: '/projects/abc' },
57
+ app,
58
+ routeRegistry,
59
+ }),
60
+ '/projects/abc',
61
+ );
62
+ });
63
+
64
+ it('falls back to authenticated entry — never /', () => {
65
+ assert.equal(
66
+ resolvePostAuthDestination({ transaction: {}, app, routeRegistry }),
67
+ '/agentsam',
68
+ );
69
+ });
70
+
71
+ it('throws AUTH_APP_UNRESOLVED without app', () => {
72
+ assert.throws(
73
+ () => resolvePostAuthDestination({ transaction: {}, app: null, routeRegistry }),
74
+ (err) => err instanceof IdentityRoutingError && err.code === 'AUTH_APP_UNRESOLVED',
75
+ );
76
+ });
77
+
78
+ it('rejects cross-app return_to then uses authenticated entry', () => {
79
+ assert.equal(
80
+ resolvePostAuthDestination({
81
+ transaction: { return_to: '/admin/orders' },
82
+ app,
83
+ routeRegistry,
84
+ }),
85
+ '/agentsam',
86
+ );
87
+ });
88
+ });
89
+
90
+ describe('app verification', () => {
91
+ it('local-studio agentsam.app.json passes auth contract', () => {
92
+ const result = verifyAppPackage(LOCAL_STUDIO, { requireShellFiles: false });
93
+ assert.equal(result.ok, true, result.errors?.join('; '));
94
+ });
95
+
96
+ it('fails when authenticated entry missing', () => {
97
+ const result = verifyAppAuthContract({
98
+ schema: 'agentsam.app.v1',
99
+ id: 'broken',
100
+ name: 'Broken',
101
+ auth: { entry: { login: 'identity.login' } },
102
+ routes: { 'identity.login': { path: '/signin' } },
103
+ }, { requireShellFiles: false });
104
+ assert.equal(result.ok, false);
105
+ assert.ok(result.errors.some((e) => /authenticated|missing|AUTH_/i.test(e)));
106
+ });
107
+ });
108
+
109
+ describe('local-only SQLite identity (zero cloud)', () => {
110
+ it('migrates, provisions password user, OAuth transaction with app_id', async () => {
111
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'agentsam-id-'));
112
+ const dbFile = path.join(dir, 'identity.sqlite');
113
+ const db = await createLocalSqliteDatabase(dbFile);
114
+ await applySqliteIdentityMigrations(db);
115
+
116
+ const adapter = createSqliteIdentityAdapter(db);
117
+ const manifest = JSON.parse(
118
+ fs.readFileSync(path.join(LOCAL_STUDIO, 'agentsam.app.json'), 'utf8'),
119
+ );
120
+ const routeRegistry = createRouteRegistry([projectionFromAppManifest(manifest)]);
121
+ const identity = createIdentityService({
122
+ adapter,
123
+ app: { id: 'local-studio' },
124
+ routeRegistry,
125
+ });
126
+
127
+ const signup = await identity.signup({
128
+ email: 'local@example.test',
129
+ password: 'test-password-ok',
130
+ displayName: 'Local',
131
+ });
132
+ assert.equal(signup.ok, true);
133
+ assert.ok(signup.sessionId);
134
+
135
+ await adapter.createOAuthTransaction({
136
+ state: 'st_test',
137
+ provider: 'cloudflare',
138
+ codeVerifier: 'verifier',
139
+ returnTo: '/agentsam',
140
+ appId: 'local-studio',
141
+ });
142
+ const tx = await adapter.consumeOAuthTransaction('st_test');
143
+ assert.equal(tx.app_id, 'local-studio');
144
+ assert.equal(tx.return_to, '/agentsam');
145
+
146
+ await assert.rejects(
147
+ () => adapter.createOAuthTransaction({
148
+ state: 'st_bad',
149
+ provider: 'cloudflare',
150
+ codeVerifier: 'v',
151
+ returnTo: '/agentsam',
152
+ }),
153
+ );
154
+
155
+ assert.equal(SESSION_POLICY.agent.defaultTtlSeconds, 900);
156
+ });
157
+ });
@@ -0,0 +1,21 @@
1
+ import assert from 'node:assert/strict';
2
+ import { describe, it } from 'node:test';
3
+ import { SESSION_POLICY, clampAgentSessionTtl } from '../src/core/session-policy.js';
4
+ import { IDENTITY_ROUTE_IDS } from '../src/contracts/route-ids.js';
5
+
6
+ describe('SESSION_POLICY', () => {
7
+ it('keeps browser and agent TTLs distinct', () => {
8
+ assert.equal(SESSION_POLICY.browser.ttlSeconds, 30 * 24 * 60 * 60);
9
+ assert.equal(SESSION_POLICY.agent.defaultTtlSeconds, 15 * 60);
10
+ assert.equal(clampAgentSessionTtl(30), 60);
11
+ assert.equal(clampAgentSessionTtl(900), 900);
12
+ assert.equal(clampAgentSessionTtl(999999), 24 * 60 * 60);
13
+ });
14
+ });
15
+
16
+ describe('IDENTITY_ROUTE_IDS', () => {
17
+ it('exposes semantic IDs only', () => {
18
+ assert.equal(IDENTITY_ROUTE_IDS.LOGIN, 'identity.login');
19
+ assert.ok(!String(IDENTITY_ROUTE_IDS.LOGIN).startsWith('/'));
20
+ });
21
+ });
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "church-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/church-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "New Iberia Church of Christ",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-church-site",
9
10
  "category": "Community",
10
11
  "industries": [
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "companions-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/companions-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "Companions of Caddo",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-companions-site",
9
10
  "category": "Community",
10
11
  "industries": [
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "floors-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/floors-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "Anything Floors & More",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-floors-site",
9
10
  "category": "Services",
10
11
  "industries": [
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "fuelnfree-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/fuelnfree-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "Fuel & Free Time",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-fuelnfree-site",
9
10
  "category": "Commerce",
10
11
  "industries": [
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "handyman-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/handyman-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "Primeaux Handyman Services",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-handyman-site",
9
10
  "category": "Services",
10
11
  "industries": [
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "insurance-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/insurance-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "Chrystal Clear Insurance",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-insurance-site",
9
10
  "category": "Professional",
10
11
  "industries": [
@@ -25,6 +25,7 @@
25
25
  "kind": "theme",
26
26
  "slug": "shinshu-site",
27
27
  "galleryPath": "apps/theme-gallery-preview/themes/shinshu-site",
28
- "installable": true
28
+ "installable": true,
29
+ "icon": "theme"
29
30
  }
30
31
  }
@@ -5,6 +5,7 @@ const THEME = {
5
5
  "displayName": "Shinshu Solutions",
6
6
  "version": "0.1.0",
7
7
  "kind": "gallery-theme",
8
+ "icon": "theme",
8
9
  "package": "@inneranimalmedia/theme-shinshu-site",
9
10
  "category": "Professional",
10
11
  "industries": [
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agentsam.inneranimalmedia.com/protocol/apps/agentsam.app.v1.schema.json",
4
+ "title": "agentsam.app.v1",
5
+ "description": "Installable AgentSam product app. Owns its routes/runtime; identity never hardcodes product URLs.",
6
+ "type": "object",
7
+ "required": ["schema", "id", "name"],
8
+ "properties": {
9
+ "schema": { "const": "agentsam.app.v1" },
10
+ "id": { "type": "string", "minLength": 1 },
11
+ "name": { "type": "string", "minLength": 1 },
12
+ "package": { "type": "string" },
13
+ "version": { "type": "string" },
14
+ "routes": {
15
+ "type": "object",
16
+ "properties": {
17
+ "entry": {
18
+ "type": "string",
19
+ "description": "Authenticated entry path after login when no return_to exists",
20
+ "pattern": "^/"
21
+ },
22
+ "mounts": {
23
+ "type": "array",
24
+ "items": {
25
+ "type": "object",
26
+ "required": ["path"],
27
+ "properties": {
28
+ "path": { "type": "string", "pattern": "^/" },
29
+ "auth": { "enum": ["required", "optional", "public"], "default": "public" },
30
+ "spa": { "type": "boolean" },
31
+ "shell": {
32
+ "type": "string",
33
+ "description": "Build artifact relative to assetRoot (must exist after build)"
34
+ }
35
+ }
36
+ }
37
+ }
38
+ }
39
+ },
40
+ "runtime": {
41
+ "type": "object",
42
+ "properties": {
43
+ "type": { "enum": ["spa", "ssr", "static"] },
44
+ "assetRoot": { "type": "string" },
45
+ "shell": { "type": "string" }
46
+ },
47
+ "additionalProperties": true
48
+ }
49
+ },
50
+ "additionalProperties": true
51
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agentsam.inneranimalmedia.com/protocol/brand/brandpack.v1.schema.json",
4
+ "title": "AgentSamBrandPack",
5
+ "type": "object",
6
+ "required": ["schema", "id"],
7
+ "properties": {
8
+ "schema": { "const": "agentsam.brandpack.v1" },
9
+ "id": { "type": "string" },
10
+ "label": { "type": "string" },
11
+ "source": {
12
+ "type": "object",
13
+ "properties": {
14
+ "repository_id": { "type": ["string", "null"] },
15
+ "snapshot_id": { "type": ["string", "null"] },
16
+ "materials": { "type": "array" }
17
+ }
18
+ },
19
+ "identity": { "type": "object" },
20
+ "tokens": {
21
+ "type": "object",
22
+ "properties": {
23
+ "palette": { "type": "object" },
24
+ "semantic": { "type": "object" },
25
+ "typography": { "type": "object" },
26
+ "spacing": { "type": "object" },
27
+ "geometry": { "type": "object" },
28
+ "effects": { "type": "object" }
29
+ }
30
+ },
31
+ "assets": { "type": "array" },
32
+ "components": { "type": "array" },
33
+ "sections": { "type": "array" },
34
+ "layouts": { "type": "array" },
35
+ "pages": { "type": "array" },
36
+ "theme_variants": { "type": "array" },
37
+ "content_refs": { "type": "array" },
38
+ "url_refs": { "type": "array" },
39
+ "evidence": { "type": "array" },
40
+ "conflicts": { "type": "array" },
41
+ "provenance": { "type": "array" }
42
+ }
43
+ }
@@ -0,0 +1,38 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://agentsam.inneranimalmedia.com/protocol/credentials/issue.v1.schema.json",
4
+ "title": "credentials.issue",
5
+ "description": "Mint an AgentSam API credential (aak_*). Host stores hash only; secret returned once.",
6
+ "type": "object",
7
+ "required": ["operation", "input", "output"],
8
+ "properties": {
9
+ "operation": { "const": "credentials.issue" },
10
+ "input": {
11
+ "type": "object",
12
+ "required": ["account_id", "name"],
13
+ "properties": {
14
+ "account_id": { "type": "string", "minLength": 1 },
15
+ "name": { "type": "string", "minLength": 1 },
16
+ "scopes": {
17
+ "type": "array",
18
+ "items": { "type": "string" },
19
+ "description": "Semantic capability scopes (e.g. repository:read, models:invoke)"
20
+ },
21
+ "environment": { "enum": ["development", "preview", "production"] },
22
+ "expires_at": { "type": ["string", "null"], "format": "date-time" },
23
+ "client_type": { "enum": ["cli", "ci", "agent", "integration"] }
24
+ }
25
+ },
26
+ "output": {
27
+ "type": "object",
28
+ "required": ["credential_id", "prefix", "secret_once", "created_at"],
29
+ "properties": {
30
+ "credential_id": { "type": "string" },
31
+ "prefix": { "type": "string" },
32
+ "secret_once": { "type": "string", "description": "Plaintext shown once; never stored by host" },
33
+ "scopes": { "type": "array", "items": { "type": "string" } },
34
+ "created_at": { "type": "string", "format": "date-time" }
35
+ }
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "agentsam.database-connection.v1",
4
+ "title": "AgentSamDatabaseConnection",
5
+ "type": "object",
6
+ "required": ["id", "engine", "provider", "connection"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "schema": { "const": "agentsam.database-connection.v1" },
10
+ "id": { "type": "string", "minLength": 1 },
11
+ "label": { "type": "string" },
12
+ "engine": { "enum": ["sqlite", "postgres", "mysql"] },
13
+ "provider": {
14
+ "enum": ["local", "cloudflare-d1", "supabase", "postgres", "mysql"]
15
+ },
16
+ "account_id": { "type": "string", "description": "Optional hosted owner. Never workspace_id." },
17
+ "connection": { "type": "object" },
18
+ "accelerator": {
19
+ "type": "object",
20
+ "required": ["driver", "configurationId"],
21
+ "properties": {
22
+ "driver": { "const": "hyperdrive" },
23
+ "configurationId": { "type": "string" },
24
+ "localConnectionStringRef": { "type": "string" }
25
+ }
26
+ },
27
+ "vectors": {
28
+ "type": "object",
29
+ "required": ["driver"],
30
+ "properties": {
31
+ "driver": {
32
+ "enum": ["none", "sqlite_exact", "sqlite_vector", "pgvector", "vectorize"]
33
+ },
34
+ "profileId": { "type": "string" },
35
+ "indexName": { "type": "string" },
36
+ "namespace": { "type": "string" }
37
+ }
38
+ },
39
+ "created_at": { "type": "string" }
40
+ }
41
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "agentsam.embedding-profile.v1",
4
+ "title": "AgentSamEmbeddingProfile",
5
+ "type": "object",
6
+ "required": ["schema", "id", "provider", "dimensions", "revision", "fingerprint"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "schema": { "const": "agentsam.embedding-profile.v1" },
10
+ "id": { "type": "string" },
11
+ "provider": { "type": "string" },
12
+ "model": { "type": ["string", "null"] },
13
+ "dimensions": { "type": "integer", "minimum": 1 },
14
+ "revision": { "type": "string" },
15
+ "parameters": { "type": "object" },
16
+ "fingerprint": { "type": "string" },
17
+ "experimental": { "type": "boolean" },
18
+ "locality": { "enum": ["local", "remote", "none"] }
19
+ }
20
+ }