@inneranimalmedia/agentsam-sdk 1.9.0 → 2.0.0-alpha.identity.1

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 (72) hide show
  1. package/DEVELOPMENT.md +21 -4
  2. package/README.md +11 -3
  3. package/docs/RELEASES.iam-mirror.md +2 -2
  4. package/docs/RELEASES.md +6 -2
  5. package/docs/identity/README.md +11 -0
  6. package/examples/gorilla-shell/README.md +7 -14
  7. package/package.json +14 -5
  8. package/packages/identity/README.md +68 -0
  9. package/packages/identity/backend/README.md +26 -0
  10. package/packages/identity/docs/getting-started.md +16 -0
  11. package/packages/identity/examples/cloudflare-worker/README.md +5 -0
  12. package/packages/identity/examples/legendary-os/README.md +27 -0
  13. package/packages/identity/package.json +30 -0
  14. package/packages/identity/scripts/postinstall-hint.mjs +8 -0
  15. package/packages/identity/scripts/preview-auth-portal.mjs +260 -0
  16. package/packages/identity/src/adapters/cloudflare-d1/index.js +4 -0
  17. package/packages/identity/src/adapters/inneranimalmedia/README.md +7 -0
  18. package/packages/identity/src/contracts/external-identity.js +35 -0
  19. package/packages/identity/src/contracts/identity.js +17 -0
  20. package/packages/identity/src/contracts/provider.js +8 -0
  21. package/packages/identity/src/contracts/session.js +9 -0
  22. package/packages/identity/src/core/accounts.js +4 -0
  23. package/packages/identity/src/core/browser-paths.js +34 -0
  24. package/packages/identity/src/core/constants.js +9 -0
  25. package/packages/identity/src/core/errors.js +8 -0
  26. package/packages/identity/src/core/http-json.js +10 -0
  27. package/packages/identity/src/core/identity.js +4 -0
  28. package/packages/identity/src/core/index.js +10 -0
  29. package/packages/identity/src/core/password-crypto.js +53 -0
  30. package/packages/identity/src/core/recovery.js +4 -0
  31. package/packages/identity/src/core/sessions.js +59 -0
  32. package/packages/identity/src/frontend/auth-portal/README.md +52 -0
  33. package/packages/identity/src/frontend/auth-portal/pages/login.html +821 -0
  34. package/packages/identity/src/frontend/auth-portal/pages/reset.html +582 -0
  35. package/packages/identity/src/frontend/auth-portal/pages/signup.html +835 -0
  36. package/packages/identity/src/frontend/auth-portal/preview/dashboard-stub.html +22 -0
  37. package/packages/identity/src/index.js +118 -0
  38. package/packages/identity/src/migrations/README.md +5 -0
  39. package/packages/identity/src/oauth/README.md +4 -0
  40. package/packages/identity/src/oauth/callback.js +24 -0
  41. package/packages/identity/src/provider-contract.js +61 -0
  42. package/packages/identity/src/providers/email/index.js +39 -0
  43. package/packages/identity/src/providers/gcp/index.js +58 -0
  44. package/packages/identity/src/providers/github/index.js +14 -0
  45. package/packages/identity/src/providers/github/mapper.js +22 -0
  46. package/packages/identity/src/providers/github/oauth.js +43 -0
  47. package/packages/identity/src/providers/github/profile.js +34 -0
  48. package/packages/identity/src/providers/google/index.js +14 -0
  49. package/packages/identity/src/providers/google/mapper.js +32 -0
  50. package/packages/identity/src/providers/google/oauth.js +41 -0
  51. package/packages/identity/src/providers/google/profile.js +14 -0
  52. package/packages/identity/src/providers/index.js +25 -0
  53. package/packages/identity/tests/identity.test.mjs +74 -0
  54. package/packages/identity/tests/preview-auth-portal.test.mjs +38 -0
  55. package/python/README.md +8 -1
  56. package/python/agentsam_sdk/repository/__init__.py +4 -18
  57. package/python/docs/gaps.md +9 -0
  58. package/python/docs/tooling.md +5 -1
  59. package/python/tests/test_d1_bloat.py +1 -1
  60. package/src/cli.js +15 -0
  61. package/src/commands/identity-preview.js +45 -0
  62. package/src/index.js +16 -0
  63. package/src/lib/core-client.js +5 -0
  64. package/templates/gorilla-shell/App.tsx +28 -28
  65. package/templates/gorilla-shell/README.md +15 -3
  66. package/test/smoke.mjs +5 -0
  67. package/examples/gorilla-shell/App.tsx +0 -540
  68. package/examples/gorilla-shell/index.html +0 -15
  69. package/examples/gorilla-shell/main.jsx +0 -9
  70. package/examples/gorilla-shell/package.json +0 -19
  71. package/examples/gorilla-shell/vite.config.js +0 -10
  72. package/src/commands/http-server.js +0 -97
package/DEVELOPMENT.md CHANGED
@@ -1,10 +1,11 @@
1
- # DEVELOPING AGENTSAM-SDK WITH INNER ANIMAL MEDIA
1
+ # Developing agentsam-sdk with Inner Animal Media
2
2
 
3
3
  ## Local smoke test
4
4
 
5
5
  ```bash
6
6
  cd agentsam-sdk
7
7
  npm test
8
+ npm run preview:auth-portal # opens /auth/login at http://127.0.0.1:8791
8
9
  ```
9
10
 
10
11
  ## Link into a scaffolded project
@@ -47,9 +48,25 @@ npx agentsam init \
47
48
  2. `npm test` passes
48
49
  3. Bump version in root `package.json`
49
50
  4. Confirm `files` includes consumer surfaces (`src`, `bin`, `python`, `protocol`, …)
50
- 5. `npm publish --access public` (manual; requires `npm login` to org)
51
- 6. Tag: `git tag vX.Y.Z && git push origin vX.Y.Z`
52
- 7. Record pairing in [`docs/RELEASES.md`](./docs/RELEASES.md): `iam@<40-sha> ↔ @inneranimalmedia/agentsam-sdk@X.Y.Z`
51
+ 5. `bash scripts/npm-publish-preflight.sh` — must print `npm whoami: inneranimalmedia`
52
+ 6. `npm publish --tag alpha --access public` (or `--tag latest` for stable)
53
+ 7. Tag: `git tag vX.Y.Z && git push origin vX.Y.Z`
54
+ 8. Record pairing in [`docs/RELEASES.md`](./docs/RELEASES.md): `iam@<40-sha> ↔ @inneranimalmedia/agentsam-sdk@X.Y.Z`
55
+
56
+ ### Publish 404 (`PUT … Not found`)
57
+
58
+ npm returns **404** (not 403) when you are logged in as the **wrong user** for scope `@inneranimalmedia`.
59
+
60
+ - Registry maintainer for this package: **`inneranimalmedia`** (see `npm view @inneranimalmedia/agentsam-sdk maintainers`)
61
+ - Fix: `npm whoami` must be `inneranimalmedia`
62
+ ```bash
63
+ npm logout
64
+ npm login # npm user inneranimalmedia (org owner), not personal GitHub-linked account
65
+ bash scripts/npm-publish-preflight.sh
66
+ npm publish --tag alpha --access public
67
+ ```
68
+ - If you use a team org on npmjs.com, invite your daily npm user as **Developer** on the org with publish rights.
69
+ - Always pass `--access public` (already in `package.json` `publishConfig`; flag is harmless).
53
70
 
54
71
  Workspace packages under `packages/*` (e.g. `@inneranimalmedia/agentsam-shell-kit`) stay
55
72
  `private: true` until separately ready — they are **not** the root publish identity.
package/README.md CHANGED
@@ -6,7 +6,7 @@ Agent Sam is a full-stack autonomous agent SDK built on Cloudflare Workers, D1,
6
6
 
7
7
  **Repo:** [github.com/SamPrimeaux/agentsam-sdk](https://github.com/SamPrimeaux/agentsam-sdk) · **npm:** `@inneranimalmedia/agentsam-sdk`
8
8
 
9
- **Protocol (dual-home, no drift):** [`protocol/README.md`](./protocol/README.md) — every tool/feature lands in this repo **and** `inneranimalmedia/agentsam-sdk/`; npm publish is manual after mirror. Python lane: [`python/`](./python/).
9
+ **Protocol (dual-home, no drift):** [`protocol/README.md`](./protocol/README.md) — every tool/feature lands in this repo **and** `inneranimalmedia/agentsam-sdk/`; npm publish is manual after mirror. Python lane: [`python/`](./python/) (stdlib-only). Optional network Python package: [`packages/agentsam-site-scrape/`](./packages/agentsam-site-scrape/) (live experimental; does not break the stdlib core).
10
10
 
11
11
  ---
12
12
 
@@ -78,17 +78,25 @@ npx @inneranimalmedia/agentsam-sdk shell
78
78
  | Piece | Location |
79
79
  |-------|----------|
80
80
  | Slash command registry | `src/lib/slash-commands.js` |
81
- | Phase 0 visual prototype | `examples/gorilla-shell/` |
81
+ | Phase 0 visual prototype | `templates/gorilla-shell/` (canonical; `examples/gorilla-shell/` is a pointer) |
82
82
  | Architecture + phases | [docs/CLI_SHELL.md](./docs/CLI_SHELL.md) |
83
83
 
84
84
  Run the prototype:
85
85
 
86
86
  ```bash
87
- cd examples/gorilla-shell && npm install && npm run dev
87
+ cd templates/gorilla-shell && npm install && npm run dev
88
88
  ```
89
89
 
90
90
  ---
91
91
 
92
+ ## Architecture (CORE default)
93
+
94
+ `src/lib/core-client.js` defaults to `https://inneranimalmedia.com`. **Correct as designed** for serving many client projects: the npm package is a thin delivery/CLI client; intelligence, tool catalog, and policy live server-side on IAM CORE.
95
+
96
+ Without an IAM backend (or `IAM_CORE_URL` / `AGENTSAM_CORE_URL` override), strangers who `npm install` get **scaffold + local CLI only** — not a freestanding hosted Agent Sam.
97
+
98
+ ---
99
+
92
100
  ## Installation
93
101
 
94
102
  ```bash
@@ -8,10 +8,10 @@ Canonical npm-side table also lives in the SDK repo: `docs/RELEASES.md`.
8
8
  | npm version | Published (UTC) | IAM git SHA (40) | Notes |
9
9
  |-------------|-----------------|------------------|-------|
10
10
  | 1.7.0 | 2026-07-14 | _(pre-receipt)_ | Prior publish |
11
- | 1.9.0 | _(pending publish)_ | `fc1628505cb3c9946c149e4c468c2e264d6f381e` | `repository.inspect` + `--dupes`; mirrored from IAM agentsam-sdk |
11
+ | 1.9.0 | 2026-08-05T07:12:21.726Z | `fc1628505cb3c9946c149e4c468c2e264d6f381e` | `repository.inspect` + `--dupes`; mirrored from IAM agentsam-sdk |
12
12
  | 1.8.0 | 2026-08-02T13:57:12.080Z | `580547301e370b77ec26bd72558979d335feedd9` | `python/` + `protocol/` in tarball; `repository.scan_bloat`; shell-kit under `packages/` |
13
13
 
14
- **Latest pairing (ready to publish):** `iam@fc1628505cb3c9946c149e4c468c2e264d6f381e` ↔ `@inneranimalmedia/agentsam-sdk@1.9.0`
14
+ **Latest pairing :** `iam@fc1628505cb3c9946c149e4c468c2e264d6f381e` ↔ `@inneranimalmedia/agentsam-sdk@1.9.0`
15
15
 
16
16
  ### Receipt rules
17
17
 
package/docs/RELEASES.md CHANGED
@@ -2,8 +2,12 @@
2
2
 
3
3
  | npm version | Published (UTC) | IAM git SHA (40) | Notes |
4
4
  |-------------|-----------------|------------------|-------|
5
+ | 2.0.0-alpha.identity | 2026-08-22 | `559bc37267f76790136004f5fa94a2bb3cd6a721` | Identity subpath (`./identity`); auth portal HTML from IAM peel; SDK git `c3a59d3`. |
6
+ | 2.0.0-alpha.identity.1 | _(pending)_ | `559bc37267f76790136004f5fa94a2bb3cd6a721` | `agentsam identity preview` + `preview:auth-portal` local 1:1 auth shell preview. |
5
7
  | 1.7.0 | 2026-07-14 | _(pre-receipt)_ | Prior publish |
6
- | 1.9.0 | _(pending publish)_ | `fc1628505cb3c9946c149e4c468c2e264d6f381e` | `python/agentsam_sdk/repository/inspect.py` (`--dupes`); CLI `agentsam repository inspect` |
8
+ | 1.9.0 | 2026-08-05T07:12:21.726Z | `fc1628505cb3c9946c149e4c468c2e264d6f381e` | `python/agentsam_sdk/repository/inspect.py` (`--dupes`); CLI `agentsam repository inspect` |
7
9
  | 1.8.0 | 2026-08-02T13:57:12.080Z | `580547301e370b77ec26bd72558979d335feedd9` | `python/` + `protocol/` in npm `files`; `repository.scan_bloat`; shell-kit folded to `packages/agentsam-shell-kit` (private). SDK git at publish: `ac52669b89ddb16fad87c42fe53f2c93ef13bd1a`. |
8
10
 
9
- **Pairing (ready to publish):** `iam@fc1628505cb3c9946c149e4c468c2e264d6f381e` ↔ `@inneranimalmedia/agentsam-sdk@1.9.0`
11
+ **Pairing (identity alpha):** `iam@559bc37267f76790136004f5fa94a2bb3cd6a721` ↔ `@inneranimalmedia/agentsam-sdk@2.0.0-alpha.identity`
12
+
13
+ **Pairing (1.9):** `iam@fc1628505cb3c9946c149e4c468c2e264d6f381e` ↔ `@inneranimalmedia/agentsam-sdk@1.9.0`
@@ -0,0 +1,11 @@
1
+ # AgentSam SDK — Identity module
2
+
3
+ See [`packages/identity/README.md`](../packages/identity/README.md).
4
+
5
+ Customer import:
6
+
7
+ ```js
8
+ import { createIdentityClient } from '@inneranimalmedia/agentsam-sdk';
9
+ ```
10
+
11
+ Alpha: `@inneranimalmedia/agentsam-sdk@2.0.0-alpha.identity`
@@ -1,22 +1,15 @@
1
- # Gorilla Shell (Phase 0)
1
+ # Gorilla Shell example (superseded)
2
2
 
3
- Game-feel terminal UI prototype — consolidated from [InnerAnimal/gorilla-mode](https://github.com/InnerAnimal/gorilla-mode) into **Agent Sam SDK**.
3
+ **Canonical scaffold:** [`../../templates/gorilla-shell/`](../../templates/gorilla-shell/)
4
4
 
5
- This is the **unique install experience** layer: pixel HUD, themed moods, slash-command demos, deploy/benchmark scenarios. Phase 1 connects real PTY via ExecOS.
6
-
7
- ## Run locally
5
+ This directory previously mirrored an older demo that hard-coded IAM D1/host
6
+ literals. Run and customize from `templates/gorilla-shell` instead:
8
7
 
9
8
  ```bash
10
- cd examples/gorilla-shell
9
+ cd templates/gorilla-shell
11
10
  npm install
12
11
  npm run dev
13
12
  ```
14
13
 
15
- ## What you see
16
-
17
- - Gorilla launch screen + sprite reactions
18
- - Themes: NIGHT, DAY, LAVA, VOID
19
- - Six demo scenarios (deploy, benchmark, D1, tail, samiam, wrangler)
20
- - Slash command registry lives in `../../src/lib/slash-commands.js`
21
-
22
- Full architecture: [docs/CLI_SHELL.md](../../docs/CLI_SHELL.md)
14
+ Demo CLI strings there use `{{PROJECT_NAME}}`, `{{D1_DATABASE_ID}}`,
15
+ `{{DASHBOARD_HOST}}`, and related placeholders — not live platform IDs.
package/package.json CHANGED
@@ -1,19 +1,24 @@
1
1
  {
2
2
  "name": "@inneranimalmedia/agentsam-sdk",
3
- "version": "1.9.0",
4
- "description": "Agent Sam is a full-stack AI agent SDK for autonomous task execution \u2014 covering data management, creative workflows, design commands, and multi-step agentic pipelines.",
3
+ "version": "2.0.0-alpha.identity.1",
4
+ "description": "Agent Sam is a full-stack AI agent SDK for autonomous task execution — covering data management, creative workflows, design commands, and multi-step agentic pipelines.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "exports": {
8
8
  ".": "./src/index.js",
9
+ "./identity": "./packages/identity/src/index.js",
10
+ "./identity/oauth/callback": "./packages/identity/src/oauth/callback.js",
11
+ "./identity/auth-portal/preview": "./packages/identity/scripts/preview-auth-portal.mjs",
9
12
  "./package.json": "./package.json"
10
13
  },
11
14
  "bin": {
12
15
  "agentsam": "src/cli.js",
13
- "agentsam-scaffold": "bin/scaffold.mjs"
16
+ "agentsam-scaffold": "bin/scaffold.mjs",
17
+ "agentsam-auth-portal": "packages/identity/scripts/preview-auth-portal.mjs"
14
18
  },
15
19
  "files": [
16
20
  "src",
21
+ "packages/identity",
17
22
  "templates",
18
23
  "docs",
19
24
  "examples",
@@ -26,11 +31,15 @@
26
31
  "DEVELOPMENT.md"
27
32
  ],
28
33
  "workspaces": [
29
- "packages/*"
34
+ "packages/agentsam-shell-kit",
35
+ "packages/identity"
30
36
  ],
31
37
  "scripts": {
32
- "test": "node test/smoke.mjs",
38
+ "test": "node test/smoke.mjs && npm --prefix packages/identity test",
39
+ "test:identity": "npm --prefix packages/identity test",
33
40
  "smoke": "node test/smoke.mjs",
41
+ "preview:auth-portal": "node packages/identity/scripts/preview-auth-portal.mjs --open",
42
+ "postinstall": "node packages/identity/scripts/postinstall-hint.mjs",
34
43
  "prepublishOnly": "npm test"
35
44
  },
36
45
  "engines": {
@@ -0,0 +1,68 @@
1
+ # Identity (`packages/identity`)
2
+
3
+ **Package #1** inside `@inneranimalmedia/agentsam-sdk` — not a separate npm product.
4
+
5
+ ```
6
+ inneranimalmedia (reference) → agentsam-sdk (product) → Legendary-OS (first external proof)
7
+ ```
8
+
9
+ ## Customer API
10
+
11
+ ```js
12
+ import { createIdentityClient } from '@inneranimalmedia/agentsam-sdk';
13
+
14
+ const identity = createIdentityClient({
15
+ portal: { brand: { name: 'Legendary OS', logoUrl: '/logo.svg' } },
16
+ });
17
+
18
+ identity.providers.google();
19
+ identity.login(request); // → Identity Service (server-side)
20
+ identity.session.fromRequest(request);
21
+ ```
22
+
23
+ ## Layout
24
+
25
+ ```
26
+ src/
27
+ core/ identity · sessions · accounts · recovery
28
+ providers/ google · github · gcp · email
29
+ oauth/ authorize/callback (extract from IAM — next sprint)
30
+ adapters/ inneranimalmedia · cloudflare-d1
31
+ contracts/
32
+ frontend/auth-portal/pages/ login · signup · reset (verbatim IAM HTML)
33
+ migrations/
34
+ examples/legendary-os/
35
+ ```
36
+
37
+ ## SDK philosophy
38
+
39
+ Ship: contracts, clients, adapters, scaffolding.
40
+
41
+ Do **not** ship in the client bundle: password DB logic, OAuth secrets, D1 assumptions.
42
+
43
+ ## Publish (alpha)
44
+
45
+ From `main` after tests pass:
46
+
47
+ ```bash
48
+ npm test
49
+ npm publish --tag alpha
50
+ ```
51
+
52
+ Install in a customer app:
53
+
54
+ ```bash
55
+ npm install @inneranimalmedia/agentsam-sdk@alpha
56
+ # or pin: @inneranimalmedia/agentsam-sdk@2.0.0-alpha.identity
57
+ ```
58
+
59
+ Subpath imports:
60
+
61
+ ```js
62
+ import { createIdentityClient } from '@inneranimalmedia/agentsam-sdk';
63
+ import { finalizeInboundOAuth } from '@inneranimalmedia/agentsam-sdk/identity/oauth/callback';
64
+ ```
65
+
66
+ ## IAM design lab
67
+
68
+ `inneranimalmedia/packages/agentsam-identity/` — contracts experiments only; **not** the package owner.
@@ -0,0 +1,26 @@
1
+ # Backend — identity runtime
2
+
3
+ Worker-side identity: providers, OAuth finalize, sessions, adapters.
4
+
5
+ ## IAM extraction map (stable production — do not rewrite)
6
+
7
+ | SDK target | IAM source today | Notes |
8
+ |------------|------------------|-------|
9
+ | `providers/google/*` | `src/core/auth/providers/google.js` | ✅ ported Sprint 2 |
10
+ | `providers/github/*` | `src/core/auth/providers/github.js` | ✅ ported Sprint 2 |
11
+ | `oauth/callback.js` | `src/api/oauth-login-callbacks.js` → `finalizeInboundOAuth` | **bulletproof path** |
12
+ | `oauth/authorize.js` | `src/api/auth.js` OAuth start handlers | PKCE + state |
13
+ | `core/session-service.js` | `src/core/auth.js` | cookie, `createLoginSession`, revoke |
14
+ | `core/account-linking.js` | `ensureIdentityPlaneBeforeSession`, `ensureAppUser` | account_identities |
15
+ | `adapters/inneranimalmedia/*` | D1 writes in auth side-effects | tenant/workspace stays adapter-only |
16
+
17
+ ## Rule
18
+
19
+ Move files; **do not** change OAuth behavior until IAM runs parallel proof (existing users, Google/GitHub callbacks, session cookie).
20
+
21
+ ## Public entry
22
+
23
+ ```js
24
+ import { createIdentity, GoogleProvider } from '@agentsam/identity';
25
+ // resolves to backend/index.js
26
+ ```
@@ -0,0 +1,16 @@
1
+ # Getting started with @agentsam/identity
2
+
3
+ 1. Install: `npm install @agentsam/identity`
4
+ 2. Configure providers and storage adapter
5
+ 3. Wire Worker routes for OAuth callback + session cookie
6
+
7
+ Full plan: Phase 1–9 in IAM `plans/active/AGENTSAM-IDENTITY-SDK-PRODUCTIZATION-2026-08.md`
8
+
9
+ ```js
10
+ import { createIdentity, GoogleProvider } from '@agentsam/identity';
11
+
12
+ const identity = createIdentity({
13
+ providers: [GoogleProvider],
14
+ storage: { adapter: 'cloudflare-d1', binding: 'DB' },
15
+ });
16
+ ```
@@ -0,0 +1,5 @@
1
+ # Cloudflare Worker + D1 example (Phase 7)
2
+
3
+ Minimal worker wiring for `@agentsam/identity` with `adapters/cloudflare-d1`.
4
+
5
+ Scaffold lands in Sprint 5 after IAM adapter proves the storage contract.
@@ -0,0 +1,27 @@
1
+ # Legendary-OS — @agentsam/identity customer proof
2
+
3
+ Target: fresh install path (Phase 7).
4
+
5
+ ## Day 1
6
+
7
+ ```bash
8
+ npm install @agentsam/identity
9
+ npx agentsam identity init --adapter cloudflare-d1
10
+ ```
11
+
12
+ ## Day 2 proof checklist
13
+
14
+ - [ ] Email signup → session cookie
15
+ - [ ] Email login
16
+ - [ ] Logout clears session
17
+ - [ ] Google OAuth round-trip
18
+ - [ ] GitHub OAuth round-trip
19
+
20
+ ## Day 3
21
+
22
+ - [ ] Workspace creation on first login
23
+ - [ ] Dashboard requires auth
24
+
25
+ Record curl transcripts and D1 row counts in `PROOF.md` when complete.
26
+
27
+ See: `inneranimalmedia/plans/active/AGENTSAM-IDENTITY-SDK-PRODUCTIZATION-2026-08.md`
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@inneranimalmedia/agentsam-sdk-identity",
3
+ "version": "2.0.0-alpha.identity.1",
4
+ "private": true,
5
+ "type": "module",
6
+ "description": "Identity module for @inneranimalmedia/agentsam-sdk (workspace — publish via root SDK)",
7
+ "main": "./src/index.js",
8
+ "exports": {
9
+ ".": "./src/index.js",
10
+ "./provider-contract": "./src/provider-contract.js",
11
+ "./providers": "./src/providers/index.js",
12
+ "./providers/google": "./src/providers/google/index.js",
13
+ "./providers/github": "./src/providers/github/index.js",
14
+ "./providers/gcp": "./src/providers/gcp/index.js",
15
+ "./providers/email": "./src/providers/email/index.js",
16
+ "./contracts/identity": "./src/contracts/identity.js",
17
+ "./contracts/session": "./src/contracts/session.js",
18
+ "./contracts/provider": "./src/contracts/provider.js",
19
+ "./contracts/external-identity": "./src/contracts/external-identity.js",
20
+ "./oauth/callback": "./src/oauth/callback.js",
21
+ "./frontend/auth-portal/*": "./src/frontend/auth-portal/*"
22
+ },
23
+ "scripts": {
24
+ "test": "node --test tests/*.test.mjs",
25
+ "preview:auth-portal": "node scripts/preview-auth-portal.mjs --open"
26
+ },
27
+ "engines": {
28
+ "node": ">=20"
29
+ }
30
+ }
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ if (process.env.CI || process.env.AGENTSAM_SDK_SKIP_POSTINSTALL) process.exit(0);
3
+
4
+ console.log(`
5
+ @inneranimalmedia/agentsam-sdk — auth portal preview (local, 1:1 IAM HTML):
6
+ npx agentsam identity preview --open
7
+ npm run preview:auth-portal
8
+ `);
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Local static preview for IAM auth portal HTML (1:1 paths: /auth/login, /auth/signup, /auth/reset).
4
+ * API routes are stubbed so forms and globe-exit transitions work without a Worker.
5
+ */
6
+ import http from 'node:http';
7
+ import fs from 'node:fs/promises';
8
+ import path from 'node:path';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { spawn } from 'node:child_process';
11
+
12
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
+ export const AUTH_PORTAL_PAGES_DIR = path.resolve(__dirname, '../src/frontend/auth-portal/pages');
14
+ const PREVIEW_DIR = path.resolve(__dirname, '../src/frontend/auth-portal/preview');
15
+
16
+ const PAGE_ROUTES = {
17
+ '/auth/login': 'login.html',
18
+ '/auth/signup': 'signup.html',
19
+ '/auth/reset': 'reset.html',
20
+ };
21
+
22
+ const MIME = {
23
+ '.html': 'text/html; charset=utf-8',
24
+ '.css': 'text/css; charset=utf-8',
25
+ '.js': 'application/javascript; charset=utf-8',
26
+ '.svg': 'image/svg+xml',
27
+ '.png': 'image/png',
28
+ '.jpg': 'image/jpeg',
29
+ '.webp': 'image/webp',
30
+ };
31
+
32
+ function parseArgs(argv) {
33
+ const opts = { port: 8791, host: '127.0.0.1', open: false };
34
+ for (let i = 0; i < argv.length; i += 1) {
35
+ const arg = argv[i];
36
+ if (arg === '--open' || arg === '-o') opts.open = true;
37
+ else if (arg === '--port' || arg === '-p') opts.port = Number(argv[++i]) || opts.port;
38
+ else if (arg === '--host' || arg === '-H') opts.host = argv[++i] || opts.host;
39
+ else if (arg === '--help' || arg === '-h') {
40
+ console.log(`
41
+ Auth portal preview — same routes as IAM production HTML shells
42
+
43
+ Usage:
44
+ agentsam identity preview [--port 8791] [--open]
45
+ npm run preview:auth-portal
46
+
47
+ Pages:
48
+ /auth/login /auth/signup /auth/reset
49
+
50
+ Preview credentials (any host): email preview@example.com · password preview
51
+ OAuth buttons → stub page with link to globe-exit demo
52
+ `);
53
+ process.exit(0);
54
+ }
55
+ }
56
+ return opts;
57
+ }
58
+
59
+ function json(res, status, body) {
60
+ const payload = JSON.stringify(body);
61
+ res.writeHead(status, {
62
+ 'Content-Type': 'application/json; charset=utf-8',
63
+ 'Content-Length': Buffer.byteLength(payload),
64
+ });
65
+ res.end(payload);
66
+ return true;
67
+ }
68
+
69
+ async function readText(filePath) {
70
+ return fs.readFile(filePath, 'utf8');
71
+ }
72
+
73
+ async function serveFile(res, filePath) {
74
+ const ext = path.extname(filePath);
75
+ const body = await fs.readFile(filePath);
76
+ res.writeHead(200, { 'Content-Type': MIME[ext] || 'application/octet-stream' });
77
+ res.end(body);
78
+ }
79
+
80
+ function hubHtml(baseUrl) {
81
+ return `<!DOCTYPE html>
82
+ <html lang="en">
83
+ <head>
84
+ <meta charset="UTF-8" />
85
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
86
+ <title>Auth portal preview | Agent Sam SDK</title>
87
+ <style>
88
+ body { font-family: Inter, system-ui, sans-serif; background: #050508; color: #e2e8f0; margin: 0; padding: 32px; line-height: 1.5; }
89
+ main { max-width: 640px; margin: 0 auto; }
90
+ h1 { font-size: 1.35rem; margin-bottom: 0.25rem; }
91
+ p.muted { color: #94a3b8; font-size: 0.95rem; }
92
+ ul { padding-left: 1.2rem; }
93
+ a { color: #38bdf8; }
94
+ code { background: rgba(255,255,255,0.08); padding: 2px 6px; border-radius: 4px; }
95
+ .card { margin-top: 24px; padding: 20px; border: 1px solid rgba(255,255,255,0.12); border-radius: 12px; background: rgba(255,255,255,0.04); }
96
+ </style>
97
+ </head>
98
+ <body>
99
+ <main>
100
+ <h1>Auth portal preview</h1>
101
+ <p class="muted">Static HTML copied from IAM <code>static/pages/auth/*</code> — paths match production.</p>
102
+ <div class="card">
103
+ <strong>Pages</strong>
104
+ <ul>
105
+ <li><a href="${baseUrl}/auth/login">/auth/login</a></li>
106
+ <li><a href="${baseUrl}/auth/signup">/auth/signup</a></li>
107
+ <li><a href="${baseUrl}/auth/reset">/auth/reset</a></li>
108
+ <li><a href="${baseUrl}/auth/login?globe_exit=1&amp;next=/preview/dashboard">Globe exit demo</a></li>
109
+ </ul>
110
+ <p><strong>Preview login:</strong> <code>preview@example.com</code> / <code>preview</code> (triggers success + globe transition)</p>
111
+ <p class="muted">OAuth buttons open a stub — use the globe-exit link to verify the post-login animation.</p>
112
+ </div>
113
+ </main>
114
+ </body>
115
+ </html>`;
116
+ }
117
+
118
+ function oauthStubHtml(provider, baseUrl) {
119
+ const label = provider === 'github' ? 'GitHub' : 'Google';
120
+ return `<!DOCTYPE html>
121
+ <html lang="en"><head><meta charset="UTF-8" /><title>OAuth preview (${label})</title>
122
+ <style>body{font-family:system-ui;background:#050508;color:#e2e8f0;padding:32px;max-width:520px;margin:auto;line-height:1.5}a{color:#38bdf8}</style>
123
+ </head><body>
124
+ <h1>OAuth preview — ${label}</h1>
125
+ <p>In production this redirects to the provider. In preview mode, use the link below to simulate a successful return and globe exit.</p>
126
+ <p><a href="${baseUrl}/auth/login?globe_exit=1&amp;next=/preview/dashboard">Simulate OAuth success (globe exit)</a></p>
127
+ <p><a href="${baseUrl}/auth/login">Back to sign in</a></p>
128
+ </body></html>`;
129
+ }
130
+
131
+ async function handleApi(req, res, url) {
132
+ const { pathname } = url;
133
+ if (req.method === 'POST' && pathname === '/api/auth/login') {
134
+ let body = '';
135
+ for await (const chunk of req) body += chunk;
136
+ let parsed = {};
137
+ try { parsed = JSON.parse(body || '{}'); } catch { /* preview */ }
138
+ const email = String(parsed.email || '').trim().toLowerCase();
139
+ const password = String(parsed.password || '');
140
+ if (email === 'preview@example.com' && password === 'preview') {
141
+ return json(res, 200, {
142
+ ok: true,
143
+ redirect: parsed.next && String(parsed.next).startsWith('/') ? parsed.next : '/preview/dashboard',
144
+ });
145
+ }
146
+ return json(res, 401, { ok: false, error: 'Invalid Identity or Access Key (preview: preview@example.com / preview)' });
147
+ }
148
+ if (req.method === 'POST' && pathname === '/api/auth/backup-code') {
149
+ return json(res, 200, { ok: true, redirect: '/preview/dashboard' });
150
+ }
151
+ if (req.method === 'POST' && pathname === '/api/auth/password-reset/request') {
152
+ return json(res, 200, { ok: true, message: 'If an account exists, a reset link was sent (preview stub).' });
153
+ }
154
+ if (req.method === 'POST' && pathname === '/api/auth/password-reset/confirm') {
155
+ return json(res, 200, { ok: true, redirect: '/auth/login?reset=success' });
156
+ }
157
+ if (req.method === 'GET' && pathname.startsWith('/api/oauth/')) {
158
+ const provider = pathname.includes('github') ? 'github' : 'google';
159
+ const baseUrl = `${url.protocol}//${url.host}`;
160
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
161
+ res.end(oauthStubHtml(provider, baseUrl));
162
+ return true;
163
+ }
164
+ return false;
165
+ }
166
+
167
+ export async function createAuthPortalPreviewServer(opts = {}) {
168
+ const host = opts.host ?? '127.0.0.1';
169
+ const port = opts.port ?? 8791;
170
+
171
+ const server = http.createServer(async (req, res) => {
172
+ try {
173
+ const url = new URL(req.url || '/', `http://${req.headers.host || `${host}:${port}`}`);
174
+
175
+ if (await handleApi(req, res, url)) return;
176
+
177
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
178
+ res.writeHead(405);
179
+ res.end('Method not allowed');
180
+ return;
181
+ }
182
+
183
+ if (url.pathname === '/' || url.pathname === '/preview') {
184
+ const baseUrl = `${url.protocol}//${url.host}`;
185
+ res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
186
+ res.end(hubHtml(baseUrl));
187
+ return;
188
+ }
189
+
190
+ const pageFile = PAGE_ROUTES[url.pathname];
191
+ if (pageFile) {
192
+ await serveFile(res, path.join(AUTH_PORTAL_PAGES_DIR, pageFile));
193
+ return;
194
+ }
195
+
196
+ if (url.pathname === '/preview/dashboard') {
197
+ const file = path.join(PREVIEW_DIR, 'dashboard-stub.html');
198
+ await serveFile(res, file);
199
+ return;
200
+ }
201
+
202
+ res.writeHead(404, { 'Content-Type': 'text/plain; charset=utf-8' });
203
+ res.end('Not found');
204
+ } catch (err) {
205
+ res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });
206
+ res.end(err?.message || 'Server error');
207
+ }
208
+ });
209
+
210
+ await new Promise((resolve, reject) => {
211
+ server.once('error', reject);
212
+ server.listen(port, host, resolve);
213
+ });
214
+
215
+ const address = server.address();
216
+ const boundPort = typeof address === 'object' && address ? address.port : port;
217
+ const baseUrl = `http://${host}:${boundPort}`;
218
+
219
+ return { server, host, port: boundPort, baseUrl };
220
+ }
221
+
222
+ function openBrowser(url) {
223
+ const platform = process.platform;
224
+ const cmd = platform === 'darwin' ? 'open' : platform === 'win32' ? 'start' : 'xdg-open';
225
+ const child = spawn(cmd, [url], { stdio: 'ignore', detached: true });
226
+ child.unref();
227
+ }
228
+
229
+ async function main() {
230
+ const opts = parseArgs(process.argv.slice(2));
231
+ const { server, baseUrl } = await createAuthPortalPreviewServer(opts);
232
+
233
+ console.log(`
234
+ Auth portal preview
235
+ ───────────────────
236
+ Hub: ${baseUrl}/
237
+ Login: ${baseUrl}/auth/login
238
+ Signup: ${baseUrl}/auth/signup
239
+ Reset: ${baseUrl}/auth/reset
240
+
241
+ Preview login: preview@example.com / preview
242
+ Ctrl+C to stop
243
+ `);
244
+
245
+ if (opts.open) openBrowser(`${baseUrl}/auth/login`);
246
+
247
+ const shutdown = () => {
248
+ server.close(() => process.exit(0));
249
+ };
250
+ process.on('SIGINT', shutdown);
251
+ process.on('SIGTERM', shutdown);
252
+ }
253
+
254
+ const isMain = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
255
+ if (isMain) {
256
+ main().catch((err) => {
257
+ console.error(err);
258
+ process.exit(1);
259
+ });
260
+ }
@@ -0,0 +1,4 @@
1
+ /** Cloudflare D1 storage adapter — Sprint 5. */
2
+ export function createCloudflareD1Adapter(_env) {
3
+ throw new Error('cloudflare_d1_adapter_not_implemented');
4
+ }
@@ -0,0 +1,7 @@
1
+ # InnerAnimalMedia adapter (Sprint 3+)
2
+
3
+ Maps IAM D1 tables (`auth_users`, `accounts`, `account_identities`, `auth_sessions`, …)
4
+ into portable AgentSam Identity contracts.
5
+
6
+ IAM-specific behavior (tenant resolution, workspace membership, OAuth callback wiring)
7
+ stays here — not in `providers/`.