@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.
- package/AGENTSAM.md +6 -0
- package/README.md +16 -1
- package/bin/agentsam +16 -1
- package/docs/BRAND_INTELLIGENCE.md +1 -1
- package/docs/architecture/AGENTSAM_DISTRIBUTION_OWNERSHIP.md +176 -0
- package/docs/architecture/AGENTSAM_GO_RUNTIME.md +282 -0
- package/docs/architecture/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/FS_E2E_CLOSURE_RECEIPT.md +59 -0
- package/docs/architecture/LOCAL_FS_AUTHORITY.md +38 -0
- package/docs/architecture/LOCAL_STUDIO_CLOUDFLARE_OAUTH.md +28 -0
- package/docs/architecture/PLAN_CLI_AND_LOCAL_STUDIO_DESKTOP.md +96 -0
- package/docs/architecture/SAM_ACTIVITY_RECOVERY_RECEIPT.md +39 -0
- package/docs/architecture/SAM_DECISION_WORK_RECEIPT.md +54 -0
- package/docs/architecture/SAM_KERNEL.md +181 -0
- package/docs/architecture/SAM_MACHINE_NORMALIZATION_PRECOMMIT_REPORT.md +208 -0
- package/docs/architecture/SLASH_SKILLS_PORTABLE.md +116 -0
- package/docs/architecture/fs-e2e-receipt.latest.json +42 -0
- package/docs/architecture/previews/codebaseindex-guided-path/CODEBASEINDEX_GUIDED_PATH.md +202 -0
- package/docs/architecture/previews/codebaseindex-guided-path/index.html +321 -0
- package/migrations/d1/0010_portable_tickets_memory.sql +140 -0
- package/migrations/d1/0011_agentsam_skill_v2.sql +185 -0
- package/migrations/d1/0011b_agentsam_skill_v2_cutover.sql +22 -0
- package/migrations/d1/0011c_agentsam_skill_v2_backfill.sql +76 -0
- package/migrations/d1/0011d_agentsam_skill_v2_retrieval_revisions.sql +50 -0
- package/migrations/d1/0012_agentsam_tools_required_seed.sql +67 -0
- package/migrations/d1/0013_identity_oauth_states.sql +15 -0
- package/migrations/d1/0014_auth_event_log.sql +20 -0
- package/migrations/d1/0015_identity_oauth_state_app_id.sql +3 -0
- package/migrations/d1/README_PORTABLE_CONTROL_PLANE.md +16 -0
- package/migrations/sqlite/agentsam_skill_retrieval.portable.sql +42 -0
- package/package.json +19 -4
- package/packages/agentsam-contracts/src/errors.ts +16 -0
- package/packages/agentsam-errors/src/envelope.js +53 -0
- package/packages/agentsam-errors/src/index.js +1 -0
- package/packages/agentsam-errors/src/recovery.js +301 -0
- package/packages/agentsam-knowledge/src/providers/index.js +18 -6
- package/packages/connectors/cloudflare/src/routes.js +9 -0
- package/packages/connectors/cloudflare/tests/connector.test.mjs +26 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/agentsam.feature.json +1 -1
- package/packages/identity/.agentsam/features/oauth-login-portal/routes.json +11 -2
- package/packages/identity/docs/PORTABLE_IDENTITY_ARCHITECTURE.md +50 -0
- package/packages/identity/migrations/D1_SCHEMA_MAPPING.md +31 -0
- package/packages/identity/migrations/sqlite/001_identity_core.sql +99 -0
- package/packages/identity/migrations/sqlite/002_identity_oauth_client.sql +38 -0
- package/packages/identity/migrations/sqlite/003_identity_oauth_server.sql +64 -0
- package/packages/identity/package.json +2 -2
- package/packages/identity/src/adapters/cloudflare-d1/index.js +122 -22
- package/packages/identity/src/adapters/sqlite/index.js +319 -0
- package/packages/identity/src/app/verify-app.js +95 -0
- package/packages/identity/src/contracts/identity-store.js +115 -0
- package/packages/identity/src/contracts/route-ids.js +30 -0
- package/packages/identity/src/contracts/route-projection.js +218 -0
- package/packages/identity/src/contracts/routes.js +11 -0
- package/packages/identity/src/core/browser-paths.js +4 -5
- package/packages/identity/src/core/constants.js +13 -8
- package/packages/identity/src/core/session-policy.js +32 -0
- package/packages/identity/src/frontend/auth-portal/pages/login.html +10 -10
- package/packages/identity/src/frontend/auth-portal/pages/reset.html +3 -3
- package/packages/identity/src/frontend/auth-portal/pages/signup.html +3 -3
- package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +1 -1
- package/packages/identity/src/index.js +25 -0
- package/packages/identity/src/oauth/README.md +10 -4
- package/packages/identity/src/oauth/credentials.js +20 -13
- package/packages/identity/src/oauth/finalize-inbound.js +1 -1
- package/packages/identity/src/oauth/iam-platform.js +8 -7
- package/packages/identity/src/oauth/redirect-paths.js +27 -36
- package/packages/identity/src/server/identity-service.js +30 -13
- package/packages/identity/src/server/mount-policy.js +30 -0
- package/packages/identity/src/server/post-auth.js +79 -0
- package/packages/identity/src/server/worker-router.js +104 -72
- package/packages/identity/tests/finalize-inbound-oauth.test.mjs +6 -6
- package/packages/identity/tests/iam-provider.test.mjs +1 -1
- package/packages/identity/tests/identity-service.test.mjs +36 -5
- package/packages/identity/tests/oauth-credentials.test.mjs +3 -1
- package/packages/identity/tests/portable-identity-architecture.test.mjs +157 -0
- package/packages/identity/tests/session-routes-policy.test.mjs +21 -0
- package/packages/theme-church-site/package.json +2 -1
- package/packages/theme-church-site/src/index.js +1 -0
- package/packages/theme-companions-site/package.json +2 -1
- package/packages/theme-companions-site/src/index.js +1 -0
- package/packages/theme-floors-site/package.json +2 -1
- package/packages/theme-floors-site/src/index.js +1 -0
- package/packages/theme-fuelnfree-site/package.json +2 -1
- package/packages/theme-fuelnfree-site/src/index.js +1 -0
- package/packages/theme-handyman-site/package.json +2 -1
- package/packages/theme-handyman-site/src/index.js +1 -0
- package/packages/theme-insurance-site/package.json +2 -1
- package/packages/theme-insurance-site/src/index.js +1 -0
- package/packages/theme-shinshu-site/package.json +2 -1
- package/packages/theme-shinshu-site/src/index.js +1 -0
- package/protocol/apps/agentsam.app.v1.schema.json +51 -0
- package/protocol/brand/brandpack.v1.schema.json +43 -0
- package/protocol/credentials/issue.v1.schema.json +38 -0
- package/protocol/database/connection.v1.schema.json +41 -0
- package/protocol/embeddings/embedding-profile.v1.schema.json +20 -0
- package/protocol/errors/error-envelope.schema.json +135 -1
- package/protocol/errors/recovery.v1.schema.json +50 -0
- package/protocol/runtime/workspace-fs.v1.schema.json +71 -0
- package/protocol/sam/activity.v1.schema.json +48 -0
- package/protocol/sam/answer.v1.schema.json +35 -0
- package/protocol/sam/calibration.v1.schema.json +21 -0
- package/protocol/sam/decision-receipt.v1.schema.json +29 -0
- package/protocol/sam/evaluation.v1.schema.json +19 -0
- package/protocol/sam/operation.schema.json +66 -0
- package/protocol/sam/outcome.v1.schema.json +36 -0
- package/protocol/sam/question.v1.schema.json +26 -0
- package/protocol/sam/registry.seed.json +153 -0
- package/protocol/sam/result.schema.json +53 -0
- package/protocol/sam/state.v1.schema.json +23 -0
- package/protocol/skills/agentsam.interaction.v1.schema.json +50 -0
- package/protocol/skills/agentsam.skill.v1.schema.json +57 -0
- package/protocol/ui/icon-registry.mjs +226 -0
- package/protocol/ui/icon.v1.schema.json +51 -0
- package/skills/README.md +22 -9
- package/skills/agentsam-codebaseindex/SKILL.md +225 -0
- package/skills/catalog.json +14 -0
- package/src/cli/command-catalog.js +130 -0
- package/src/cli/dispatch.js +48 -0
- package/src/cli.js +43 -1
- package/src/commands/api-key.js +244 -0
- package/src/commands/app.js +60 -28
- package/src/commands/brand.js +17 -19
- package/src/commands/codebaseindex.js +688 -0
- package/src/commands/env.js +152 -25
- package/src/commands/go.js +366 -53
- package/src/commands/interaction-clack.js +115 -0
- package/src/commands/models.js +1 -1
- package/src/commands/providers.js +62 -14
- package/src/commands/shell.js +43 -2
- package/src/commands/skill.js +248 -0
- package/src/commands/skills.js +1 -1
- package/src/commands/start-local.js +4 -0
- package/src/commands/whoami.js +90 -18
- package/src/go/build.js +229 -39
- package/src/go/cloudflare.js +506 -105
- package/src/go/container.js +120 -0
- package/src/go/contract.js +9 -4
- package/src/go/discover.js +149 -33
- package/src/go/index.js +15 -3
- package/src/go/native-probe-runner.mjs +119 -0
- package/src/go/{registry.js → official-registry.js} +64 -7
- package/src/go/official-release.js +10 -0
- package/src/go/receipts.js +77 -10
- package/src/go/verify.js +9 -2
- package/src/index.js +27 -0
- package/src/indexing/ingest/discover-models.js +298 -0
- package/src/indexing/ingest/inventory.js +243 -0
- package/src/indexing/ingest/job-graph.js +181 -0
- package/src/indexing/ingest/materials.js +210 -0
- package/src/lib/provider-credentials.js +63 -21
- package/src/lib/slash-commands.js +1 -0
- package/src/local-fs/capability.js +121 -0
- package/src/local-fs/freshness.js +75 -0
- package/src/local-fs/index.js +385 -0
- package/src/local-fs/paths.js +100 -0
- package/src/local-pty/server.js +295 -19
- package/src/mcp/client.js +2 -2
- package/src/models/ai-access-onboarding.js +112 -0
- package/src/models/discovery.js +10 -2
- package/src/models/inventory-core.js +9 -1
- package/src/sam/activity/index.js +183 -0
- package/src/sam/client.js +252 -0
- package/src/sam/decision/calibration.js +109 -0
- package/src/sam/decision/confidence.js +126 -0
- package/src/sam/decision/evaluate.js +157 -0
- package/src/sam/decision/evaluators/deterministic.js +341 -0
- package/src/sam/decision/evaluators/heuristic.js +61 -0
- package/src/sam/decision/evaluators/select.js +50 -0
- package/src/sam/decision/evaluators/semantic.js +149 -0
- package/src/sam/decision/hierarchical.js +61 -0
- package/src/sam/decision/index.js +53 -0
- package/src/sam/decision/policy.js +86 -0
- package/src/sam/decision/questions.js +120 -0
- package/src/sam/decision/receipt.js +148 -0
- package/src/sam/decision/state.js +117 -0
- package/src/sam/decision/types.js +22 -0
- package/src/sam/decision/validate.js +200 -0
- package/src/sam/define.js +51 -0
- package/src/sam/index.js +65 -0
- package/src/sam/operations/brand-scan.js +62 -0
- package/src/sam/operations/cad-blender-inspect.js +36 -0
- package/src/sam/operations/codebaseindex-ingest.js +49 -0
- package/src/sam/operations/decision-evaluate.js +59 -0
- package/src/sam/operations/planning-astar.js +77 -0
- package/src/sam/operations/planning-goap.js +60 -0
- package/src/sam/operations/repository-inspect.js +72 -0
- package/src/sam/operations/security-scan.js +33 -0
- package/src/sam/operations/terminal-exec.js +29 -0
- package/src/sam/planning/astar.js +311 -0
- package/src/sam/planning/goap.js +177 -0
- package/src/sam/planning/index.js +21 -0
- package/src/sam/planning/state.js +84 -0
- package/src/sam/registry.js +48 -0
- package/src/sam/result.js +77 -0
- package/src/sam/seed.js +44 -0
- package/src/sam/types.js +91 -0
- package/src/skills/catalog.js +64 -0
- package/src/skills/content-resolver.js +124 -0
- package/src/skills/hosted-store.js +37 -0
- package/src/skills/index.js +29 -64
- package/src/skills/interaction.js +102 -0
- package/src/skills/local-store.js +228 -0
- package/src/skills/manifest.js +104 -0
- package/src/skills/metrics.js +31 -0
- package/src/skills/registry.js +184 -0
- package/src/skills/runtime.js +287 -0
- package/src/skills/slash.js +44 -0
- package/src/ui/cli/help.js +94 -101
- package/test/cli/api-key-env-whoami.test.mjs +129 -0
- package/test/cli/codebaseindex-plan-ux.test.mjs +37 -0
- package/test/cli/go.test.mjs +62 -5
- package/test/cli/skill-npm-and-env.test.mjs +52 -0
- package/test/cli/wireframes-go-registry.test.mjs +87 -2
- package/test/go/build-source-identity.test.mjs +31 -0
- package/test/go/cloudflare-probe.test.mjs +274 -10
- package/test/go/distribution.test.mjs +28 -0
- package/test/integration/ai-access-onboarding.test.mjs +47 -0
- package/test/integration/cli-help.test.mjs +1 -1
- package/test/integration/cms-site-tenancy-contract.test.mjs +6 -6
- package/test/integration/codebaseindex-ingest.test.mjs +166 -0
- package/test/integration/icon-registry.test.mjs +67 -0
- package/test/integration/ingest-discover-models.test.mjs +30 -0
- package/test/integration/install-script.test.mjs +12 -9
- package/test/integration/local-fs.test.mjs +113 -0
- package/test/integration/provider-env-cli.test.mjs +2 -1
- package/test/integration/sam-activity-recovery.test.mjs +147 -0
- package/test/integration/sam-decision.test.mjs +584 -0
- package/test/integration/sam-kernel.test.mjs +99 -0
- package/test/integration/sam-planning-astar.test.mjs +279 -0
- package/test/integration/skill-runtime.test.mjs +240 -0
- package/test/integration/studio-fs-pty-e2e.test.mjs +294 -0
- package/test/models.test.mjs +14 -7
- 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
|
+
"version": "2.6.4",
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace
|
|
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 ??
|
|
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
|
|
35
|
-
*
|
|
36
|
-
*
|
|
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({
|
|
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
|
-
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
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) {
|