{"_id":"@altimist/altimist-id-consumer","_rev":"4-c5e9c331d6d235cdc8ec6868e9eedcbb","name":"@altimist/altimist-id-consumer","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@altimist/altimist-id-consumer","version":"0.1.0","_id":"@altimist/altimist-id-consumer@0.1.0","maintainers":[{"name":"altimistdev","email":"developer@altimist.com"}],"dist":{"shasum":"5154fdb64fac1c325dc70b0a44b098f28d8b10a9","tarball":"https://registry.npmjs.org/@altimist/altimist-id-consumer/-/altimist-id-consumer-0.1.0.tgz","fileCount":52,"integrity":"sha512-GDT0sWQvjwITBJYjWSY0b7kus4yOLYcI1tT+eWQ5/Gkh6RGaE+R9x0WhUp1gprkCibvov83mF9EgZHIsOmc9eQ==","signatures":[{"sig":"MEUCIQD8NfAGB5UXXdCITqGl33gwIq1rttudSbrGnyj0imceaQIgVCWemkH4HtLH9e/kGjDCoL/+JeuvOXqF+tnNb2C+9OM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":95619},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./prisma":{"types":"./dist/prisma.d.ts","import":"./dist/prisma.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.js"}},"gitHead":"572ca7f56bb29b65b0fd4f80cee6e72eee071dc9","private":false,"scripts":{"lint":"echo \"(no lint configured)\" && exit 0","test":"vitest run","build":"tsc","test:cov":"vitest run --coverage","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"altimistdev","email":"developer@altimist.com"},"_npmVersion":"11.7.0","description":"Consumer-side library for AltimistID auth in Next.js apps — the ADR-031 Node-runtime middleware choke point (DB-backed sessions, default-deny route policy, VC-derived roles, hosted-handoff popup login) as an installable package. Counterpart to @altimist/d","directories":{},"_nodeVersion":"24.13.0","dependencies":{"zod":"^3.23.8","iron-session":"^8.0.4","@altimist/did-web-client":"^0.7.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"next":"^15.5.19","vitest":"^4.1.8","typescript":"^5.7.0","@types/node":"^22.10.0","@vitest/coverage-v8":"^4.1.8"},"peerDependencies":{"next":">=15.5.0","@prisma/client":">=5.0.0"},"peerDependenciesMeta":{"@prisma/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/altimist-id-consumer_0.1.0_1781696175358_0.9466813850841367","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@altimist/altimist-id-consumer","version":"0.1.1","_id":"@altimist/altimist-id-consumer@0.1.1","maintainers":[{"name":"altimistdev","email":"developer@altimist.com"}],"dist":{"shasum":"a1546a49b5b63f37a7542b79de409c441109ae3a","tarball":"https://registry.npmjs.org/@altimist/altimist-id-consumer/-/altimist-id-consumer-0.1.1.tgz","fileCount":52,"integrity":"sha512-6F8KPABVGxaiW0o5b/1TSCgXlR+FTYNCTZuq91GU+U6KFYfGgvKMrklvSBykpLzRQgUSW3f2sy1std8i3FWppA==","signatures":[{"sig":"MEUCIA1js6Hh5EdpcQbro8KOwjcj3L8tkwpgp8cbQqE+IQvrAiEArB+8q8s8ic3aD2mFLMAWBxLBHkn9JDcaFl5JBrDEuN8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":102444},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./prisma":{"types":"./dist/prisma.d.ts","import":"./dist/prisma.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.js"}},"gitHead":"375fd159f6e5e8abdbe18afae2cb8753e93ca5f8","private":false,"scripts":{"lint":"echo \"(no lint configured)\" && exit 0","test":"vitest run","build":"tsc","test:cov":"vitest run --coverage","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"altimistdev","email":"developer@altimist.com"},"_npmVersion":"11.7.0","description":"Consumer-side library for AltimistID auth in Next.js apps — the ADR-031 Node-runtime middleware choke point (DB-backed sessions, default-deny route policy, VC-derived roles, hosted-handoff popup login) as an installable package. Counterpart to @altimist/d","directories":{},"_nodeVersion":"24.13.0","dependencies":{"zod":"^3.23.8","iron-session":"^8.0.4","@altimist/did-web-client":"^0.7.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"next":"^15.5.19","vitest":"^4.1.8","typescript":"^5.7.0","@types/node":"^22.10.0","@vitest/coverage-v8":"^4.1.8"},"peerDependencies":{"next":">=15.5.0","@prisma/client":">=5.0.0"},"peerDependenciesMeta":{"@prisma/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/altimist-id-consumer_0.1.1_1785401115117_0.5405241615133716","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@altimist/altimist-id-consumer","version":"0.1.2","_id":"@altimist/altimist-id-consumer@0.1.2","maintainers":[{"name":"altimistdev","email":"developer@altimist.com"}],"dist":{"shasum":"ffd065ffd5b9a4bbc2f2e679e11ec20cb4cf79fb","tarball":"https://registry.npmjs.org/@altimist/altimist-id-consumer/-/altimist-id-consumer-0.1.2.tgz","fileCount":52,"integrity":"sha512-aIGB1CfDyBwHlDseGPka4A8Ihnx2q2u/XFAREqlMGPhI0bVsCwSBEb/kGVlYru49M4osi/m6sUkdE2MQF8uAsA==","signatures":[{"sig":"MEYCIQDcT4YfZK/ioyq1EXdj82M+JkfkdPhLQ0JXPn361QcTyAIhAK/K2JmspLk7VJ2DOBQnpb8MZBnacweEm4bO8fZ6I0BN","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":105333},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20.0.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./prisma":{"types":"./dist/prisma.d.ts","import":"./dist/prisma.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.js"}},"gitHead":"5c8dc1620263f6a18834857e7a81980d5f258868","private":false,"scripts":{"lint":"echo \"(no lint configured)\" && exit 0","test":"vitest run","build":"tsc","test:cov":"vitest run --coverage","typecheck":"tsc --noEmit","test:watch":"vitest","prepublishOnly":"npm test && npm run build"},"_npmUser":{"name":"altimistdev","email":"developer@altimist.com"},"_npmVersion":"11.7.0","description":"Consumer-side library for AltimistID auth in Next.js apps — the ADR-031 Node-runtime middleware choke point (DB-backed sessions, default-deny route policy, VC-derived roles, hosted-handoff popup login) as an installable package. Counterpart to @altimist/d","directories":{},"_nodeVersion":"24.13.0","dependencies":{"zod":"^3.23.8","iron-session":"^8.0.4","@altimist/did-web-client":"^0.7.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"next":"^15.5.19","vitest":"^4.1.8","typescript":"^5.7.0","@types/node":"^22.10.0","@vitest/coverage-v8":"^4.1.8"},"peerDependencies":{"next":">=15.5.0","@prisma/client":">=5.0.0"},"peerDependenciesMeta":{"@prisma/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/altimist-id-consumer_0.1.2_1785756616291_0.5958867318610921","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@altimist/altimist-id-consumer","version":"0.1.3","description":"Consumer-side library for AltimistID auth in Next.js apps — the ADR-031 Node-runtime middleware choke point (DB-backed sessions, default-deny route policy, VC-derived roles, hosted-handoff popup login) as an installable package. Counterpart to @altimist/d","private":false,"type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./prisma":{"types":"./dist/prisma.d.ts","import":"./dist/prisma.js"},"./browser":{"types":"./dist/browser.d.ts","import":"./dist/browser.js"}},"engines":{"node":">=20.0.0"},"scripts":{"build":"tsc","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","test:cov":"vitest run --coverage","lint":"echo \"(no lint configured)\" && exit 0","prepublishOnly":"npm test && npm run build"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"dependencies":{"@altimist/did-web-client":"^0.7.2","iron-session":"^8.0.4","zod":"^3.23.8"},"peerDependencies":{"next":">=15.5.0","@prisma/client":">=5.0.0"},"peerDependenciesMeta":{"@prisma/client":{"optional":true}},"devDependencies":{"@types/node":"^22.10.0","@vitest/coverage-v8":"^4.1.8","next":"^15.5.19","typescript":"^5.7.0","vitest":"^4.1.8"},"gitHead":"4fe0f92e8b3c86ff9548e96d499faf5e762b3600","_id":"@altimist/altimist-id-consumer@0.1.3","_nodeVersion":"24.13.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-jDr59pBDIytRRO+XpeMqVdkl+sNXMM4yL5CkuwEC1P3OQ4Mxm4Qlqu3sQExhqViXP4ST8qxGObOZQMGnf15y/A==","shasum":"9fa0c1c26735b8d2a397101cfa535c2be9e51a3c","tarball":"https://registry.npmjs.org/@altimist/altimist-id-consumer/-/altimist-id-consumer-0.1.3.tgz","fileCount":52,"unpackedSize":107739,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEx7AA+eQ2t1SGP4psH85cSJLESu0cSbh1X7/Nl8hMFiAiEAzSG3owU2FIOBKjcGBk2e466b3BxFw7qnNhZ8QZuJspU="}]},"_npmUser":{"name":"altimistdev","email":"developer@altimist.com"},"directories":{},"maintainers":[{"name":"altimistdev","email":"developer@altimist.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/altimist-id-consumer_0.1.3_1785832915053_0.11243665391053836"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-17T11:36:15.089Z","modified":"2026-08-04T08:41:55.411Z","0.1.0":"2026-06-17T11:36:15.503Z","0.1.1":"2026-07-30T08:45:15.239Z","0.1.2":"2026-08-03T11:30:16.418Z","0.1.3":"2026-08-04T08:41:55.215Z"},"description":"Consumer-side library for AltimistID auth in Next.js apps — the ADR-031 Node-runtime middleware choke point (DB-backed sessions, default-deny route policy, VC-derived roles, hosted-handoff popup login) as an installable package. Counterpart to @altimist/d","maintainers":[{"name":"altimistdev","email":"developer@altimist.com"}],"readme":"# `@altimist/altimist-id-consumer`\r\n\r\nAdd AltimistID authentication to a Next.js app the way [ADR-031](https://github.com/altimist/altimist-strategy/blob/main/decisions/ADR-031-altimistid-consumer-middleware-choke-point.md) prescribes — one Node-runtime middleware choke point doing DB-backed session validation plus a **default-deny** route policy, with roles derived from verifiable credentials — without copying a dozen files between apps.\r\n\r\n```bash\r\nnpm install @altimist/altimist-id-consumer @altimist/did-web-client iron-session\r\n```\r\n\r\n> **Status:** `0.x`, initial development. The API may change until mission-control\r\n> migrates onto it (mc#336). See [`docs/specs/F-001-altimist-id-consumer-package.md`](./docs/specs/F-001-altimist-id-consumer-package.md).\r\n\r\n## What this is\r\n\r\n- **The ADR-031 pattern as a package.** A fail-closed `middleware.ts` choke point,\r\n  a default-deny route policy engine, DB-backed iron-session cookies, VC-derived\r\n  `staff`/`visitor` roles, the hosted-handoff popup login (sign-in + register),\r\n  logout, and session-revocation tooling.\r\n- **Bring-your-own data layer.** The package core has **no** Prisma dependency — it\r\n  talks to a small `AidStore` interface. Use the shipped `prismaStore` adapter for\r\n  the canonical schema, or implement `AidStore` against any database.\r\n- **No UI.** The package ships the tricky popup/`postMessage` login *behaviour*\r\n  (framework-agnostic, on `/browser`); your design system renders the components.\r\n\r\n## What this is *not*\r\n\r\n- **Not** `@altimist/did-web-client`. That library is the verification primitive\r\n  (DID + VC checks); this one is the full consumer integration that *uses* it.\r\n- **Not** an OAuth/OIDC server. Sign-in is a hosted handoff to altimist.id (where\r\n  the passkey ceremony runs); everything else is local to your app.\r\n- **Not** owner of your database schema. You own your `schema.prisma`, migrations,\r\n  and Prisma client.\r\n\r\n## Quick start\r\n\r\nA greenfield app wires up in a handful of one-line files.\r\n\r\n**1. One module assembles everything:**\r\n\r\n```ts\r\n// src/lib/aid.ts\r\nimport { createAid, configFromEnv } from '@altimist/altimist-id-consumer';\r\nimport { prismaStore } from '@altimist/altimist-id-consumer/prisma';\r\nimport { prisma } from './prisma';\r\n\r\nexport const aid = createAid({\r\n  ...configFromEnv(),              // SESSION_PASSWORD, ALTIMIST_*, API_KEY_HASH*\r\n  store: prismaStore(prisma),      // the data seam — canonical schema → no adapter code\r\n  policy: {\r\n    staffOnlyPages: ['/admin'],\r\n    visitorGetAllowlist: ['/api/public-thing'],\r\n  },\r\n});\r\n```\r\n\r\n**2. The middleware choke point:**\r\n\r\n```ts\r\n// middleware.ts\r\nimport { aid } from '@/lib/aid';\r\n\r\nexport const middleware = aid.middleware;\r\n\r\n// Next requires `config` to be a STATIC object literal — it cannot read a runtime\r\n// value (so `export const config = aid.middlewareConfig` does NOT work). The\r\n// `runtime: 'nodejs'` is load-bearing: without it the middleware runs on Edge,\r\n// where the verification deps can't load. Copy this literal verbatim.\r\nexport const config = {\r\n  runtime: 'nodejs',\r\n  matcher: [\r\n    '/((?!_next/static|_next/image|favicon.ico|manifest.json|robots.txt|sw.js|.*\\\\.(?:svg|png|ico|jpg|jpeg|webp|gif|js|css|map|txt|woff2?|webmanifest)$).*)',\r\n  ],\r\n};\r\n```\r\n\r\n> `aid.middlewareConfig` exposes the same `{ runtime, matcher }` for reference, but\r\n> Next's static analysis means you must write the literal above in `middleware.ts`.\r\n\r\n**3. The auth routes (one line each, mounted at the canonical paths):**\r\n\r\n```ts\r\n// app/api/auth/altimist/handoff/init/route.ts   → export const { POST } = aid.routes.handoffInit;\r\n// app/api/auth/altimist/register/init/route.ts  → export const { POST } = aid.routes.registerInit;  (optional)\r\n// app/api/auth/altimist/verify/route.ts         → export const { POST } = aid.routes.verify;\r\n// app/api/auth/logout/route.ts                  → export const { POST } = aid.routes.logout;\r\n// app/api/auth/me/route.ts                       → export const { GET }  = aid.routes.me;\r\n// app/auth/altimist/callback/route.ts            → export const { GET }  = aid.routes.callback;\r\n```\r\n\r\n**4. Your login UI calls the popup logic:**\r\n\r\n```tsx\r\n'use client';\r\nimport { runAltimistSignIn } from '@altimist/altimist-id-consumer/browser';\r\n// your design-system <LoginForm> calls runAltimistSignIn({ handle, onError, onSuccess })\r\n```\r\n\r\n## The data seam\r\n\r\nThe core never imports Prisma; it depends on this interface:\r\n\r\n```ts\r\ninterface AidStore {\r\n  createSession(s): Promise<void>;\r\n  findSessionByToken(token): Promise<{ userId; role; expiresAt } | null>;\r\n  deleteSession(token): Promise<void>;\r\n  deleteSessionsByHandle(handle): Promise<number>;\r\n  deleteAllSessions(): Promise<number>;\r\n  findUserByDid(did): Promise<{ id; handle; role } | null>;\r\n  findUserById(id): Promise<{ id; handle; role } | null>;\r\n  createUser(u): Promise<{ id }>;\r\n  updateUser(id, data): Promise<void>;\r\n  writeAudit(e): Promise<void>;\r\n}\r\n```\r\n\r\n`prismaStore(prisma)` implements it against the canonical schema. A consumer whose\r\nschema differs (e.g. mission-control) writes a ~40-line adapter mapping its own\r\ntables.\r\n\r\n## Canonical Prisma schema\r\n\r\nCopy into your `schema.prisma` to use `prismaStore` with no adapter code:\r\n\r\n```prisma\r\nmodel User {\r\n  id        String    @id @default(cuid())\r\n  did       String    @unique\r\n  handle    String\r\n  role      String    // 'staff' | 'visitor' — recomputed each sign-in\r\n  createdAt DateTime  @default(now())\r\n  lastLogin DateTime?\r\n  sessions  Session[]\r\n}\r\nmodel Session {\r\n  id        String   @id @default(cuid())\r\n  token     String   @unique\r\n  userId    String\r\n  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)\r\n  role      String\r\n  expiresAt DateTime\r\n  createdAt DateTime @default(now())\r\n}\r\nmodel AuthAuditLog {\r\n  id        String   @id @default(cuid())\r\n  event     String\r\n  outcome   String\r\n  metadata  Json?\r\n  createdAt DateTime @default(now())\r\n  @@index([event, createdAt])\r\n}\r\n```\r\n\r\n## Environment\r\n\r\n| Var | Purpose |\r\n|---|---|\r\n| `SESSION_PASSWORD` | iron-session sealing key (≥32 chars, **required**) |\r\n| `ALTIMIST_APP_ID` | matches your altimist.id `AppPolicy.appId` |\r\n| `ALTIMIST_ALLOWED_ISSUERS` | comma-separated `did:web` host eTLD+1s (federation; defaults to `altimist.com`) |\r\n| `API_KEY_HASH`, `API_KEY_HASH_SALT` | optional M2M X-API-Key gate |\r\n\r\nYou must also register an `AppPolicy` on altimist.id for your app (`appId`,\r\n`redirectOrigins` pointing at `https://<your-domain>/auth/altimist/callback`, and\r\n`signupOrigins` if you allow self-service register). Node-runtime middleware\r\nrequires **Next.js ≥ 15.5**.\r\n\r\n## Development\r\n\r\n```bash\r\nnpm install\r\nnpm test            # vitest\r\nnpm run typecheck   # tsc --noEmit\r\nnpm run build       # tsc to dist/\r\n```\r\n\r\n## License\r\n\r\nUNLICENSED — internal Altimist.\r\n","readmeFilename":"README.md"}