{"_id":"@alfiz/mongo","_rev":"2-3cc4f5fa5ed068b4cdb54a0966f3ed74","name":"@alfiz/mongo","dist-tags":{"latest":"0.8.1"},"versions":{"0.8.0":{"name":"@alfiz/mongo","version":"0.8.0","license":"MIT","_id":"@alfiz/mongo@0.8.0","maintainers":[{"name":"bytestorm","email":"kamil.m.arif@gmail.com"}],"dist":{"shasum":"d730d5e005edab2952bf2bfc6ccb37a4c2153f53","tarball":"https://registry.npmjs.org/@alfiz/mongo/-/mongo-0.8.0.tgz","fileCount":11,"integrity":"sha512-nSDmuVbwgkGSjGOS1iwZJYisyUz3qmPhbpC1OThXkpw2V162aJGJqdJVpMpezmO+sW2GzagSkkVrCCJ8t4l0lA==","signatures":[{"sig":"MEYCIQDR3kejvGHOKEyT3keRNt3xrl8qpRIABXZeN3RGc2ajjwIhAK0ip7SGsNVXMw8jcNH8nzONOOZ9+y0yR4WqkFYrTRCJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51793},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"07e6b3c3fda7a29b4cae65754a7798a250794375","scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit"},"_npmUser":{"name":"bytestorm","email":"kamil.m.arif@gmail.com"},"_npmVersion":"11.11.0","description":"The MongoDB storage driver for the Alfiz Application: implements the storage seam directly over the official `mongodb` driver, including the persisted invalidation log and a cross-process lease for graph-write serialization.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"@alfiz/core":"^0.8.0","@alfiz/application":"^0.8.0"},"_hasShrinkwrap":false,"devDependencies":{"mongodb":"^7.5.0","mongodb-memory-server":"^11.2.0"},"peerDependencies":{"mongodb":"^6.0.0 || ^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/mongo_0.8.0_1786225478759_0.36804376937661987","host":"s3://npm-registry-packages-npm-production"}},"0.8.1":{"name":"@alfiz/mongo","version":"0.8.1","description":"The MongoDB storage driver for the Alfiz Application: implements the storage seam directly over the official `mongodb` driver, including the persisted invalidation log and a cross-process lease for graph-write serialization.","license":"MIT","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit"},"dependencies":{"@alfiz/core":"^0.8.1","@alfiz/application":"^0.8.1"},"peerDependencies":{"mongodb":"^6.0.0 || ^7.0.0"},"devDependencies":{"mongodb":"^7.5.0","mongodb-memory-server":"^11.2.0"},"gitHead":"384e8ffec40c8db9e1b2fa52d409540d6a62ee88","_id":"@alfiz/mongo@0.8.1","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-LZel7ZBuxeuqlMTH2UhXDa8D+LL0ak1O8Wj7yQyBbCyBkqKyZpUcDs2PYYQfWnw2GFC0VHxTXYQ3Tcvl6TG/dQ==","shasum":"601be14739883b8ecb76cf8dbd9966262cb07424","tarball":"https://registry.npmjs.org/@alfiz/mongo/-/mongo-0.8.1.tgz","fileCount":11,"unpackedSize":64468,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDlHFaXWzAbRBoTzja6k9xlTMBD3DM2hWOpyziNrvvsHAiEAqWotRgwxeOGFXQpE4UKj5o43fCC5eBbo0A+tX/4sDZQ="}]},"_npmUser":{"name":"bytestorm","email":"kamil.m.arif@gmail.com"},"directories":{},"maintainers":[{"name":"bytestorm","email":"kamil.m.arif@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mongo_0.8.1_1786235075040_0.8492050147719026"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-08T21:44:38.624Z","modified":"2026-08-09T00:24:35.390Z","0.8.0":"2026-08-08T21:44:38.896Z","0.8.1":"2026-08-09T00:24:35.203Z"},"license":"MIT","description":"The MongoDB storage driver for the Alfiz Application: implements the storage seam directly over the official `mongodb` driver, including the persisted invalidation log and a cross-process lease for graph-write serialization.","maintainers":[{"name":"bytestorm","email":"kamil.m.arif@gmail.com"}],"readme":"# @alfiz/mongo\r\n\r\nThe MongoDB storage driver for the Alfiz Application. It implements the\r\nstorage seam (`StorageDriver` from `@alfiz/application`) directly over the\r\nofficial [`mongodb`](https://www.npmjs.com/package/mongodb) driver — there is\r\nno schema to merge and no code generation step; point it at a database and\r\ngo.\r\n\r\n## Construct the driver\r\n\r\n```ts\r\nimport { MongoClient } from \"mongodb\";\r\nimport { createApplication } from \"@alfiz/application\";\r\nimport { mongoDriver } from \"@alfiz/mongo\";\r\n\r\nconst client = new MongoClient(process.env.MONGO_URL!);\r\nawait client.connect();\r\n\r\nconst storage = mongoDriver(client.db(\"alfiz\"));\r\nconst app = createApplication({ storage /* ... */ });\r\n```\r\n\r\n`mongoDriver` also accepts a `Promise<Db>`, for callers that want to\r\nconstruct the Application before `client.connect()` resolves:\r\n\r\n```ts\r\nconst storage = mongoDriver(client.connect().then((c) => c.db(\"alfiz\")));\r\n```\r\n\r\nCollections (`grants`, `revokes`, `roles`, `groups`, `users`, `requests`,\r\n`catalog`, `audit`, `epoch`, `events`, `locks`) and their hot-path indexes are\r\ncreated lazily on first use — no migration step. Every row is stored with\r\nits Alfiz id as Mongo's `_id`, for free uniqueness and point reads.\r\n\r\n## Partitioned storage: several Applications, one deployment\r\n\r\nThree mechanisms. A **separate `Db` per application** —\r\n`client.db(\"alfiz_docs\")` — works as shipped with zero configuration and\r\nis strictly preferred where databases are not rationed: isolation holds by\r\nconstruction. Where one `Db` must be shared, choose a layout:\r\n\r\n```ts\r\n// Collection prefix (the default layout): docs_grants, docs_epoch, docs_locks, …\r\nconst docs = mongoDriver(db, { partition: \"docs\" });\r\n\r\n// Row partitioning: ONE shared collection set — grants, epoch, locks — with\r\n// an `app` discriminator per document and compound { app, id } _ids,\r\n// matching the Prisma v2 layout exactly. Since 0.8.1.\r\nconst docs = mongoDriver(db, { partition: \"docs\", layout: \"rows\" });\r\n```\r\n\r\nThe prefix is the physically stronger mechanism — no query can *forget*\r\nthe predicate, and indexes are unchanged — at the cost of a parallel\r\ncollection set per application, which gets noisy in Compass with many\r\nco-tenants. `layout: \"rows\"` keeps the collection list flat however many\r\napplications share the `Db`: every query the driver issues is\r\npartition-scoped through one shared helper, every index leads with `app`,\r\nand lease keys carry the partition, so co-tenants never falsely contend.\r\nBoth layouts are graded by the same isolation and mesh conformance\r\nsuites; above the seam nothing can tell them apart.\r\n\r\nEither way, a driver is pinned to its partition at construction and\r\ncannot address any other. The recommended partition key is the\r\napplication's primary catalog namespace, and the rules in a shared `Db`\r\nare **all partitioned or none** and **one layout per `Db`** — an\r\napplication that omits the option lands in the unprefixed collections\r\nbeside any legacy data, and a `\"rows\"` driver cannot see documents\r\nwritten without the discriminator (which is also why `\"rows\"` requires\r\nan explicit `partition`: there is no migrated-in-place default dataset\r\non Mongo the way there is on SQL). Because the lease already serializes\r\nacross processes, this driver qualifies for mesh WRITE edges\r\n(`StorageDriver.crossProcess`) as shipped, under either layout.\r\n\r\n## The invalidation log and cross-process locking\r\n\r\nThe `epoch`/`events` collections back the Application's\r\n`events: { persist: true }` option out of the box — no extra setup, unlike\r\nthe Prisma driver's additive schema models. `runExclusive` (graph-write\r\nserialization) is a promise-chain mutex in-process, plus a best-effort lease\r\nin the `locks` collection cross-process: two nodes writing group parentage at\r\nthe same moment cannot jointly form a cycle. An expired lease is stolen, so a\r\ncrashed holder can't wedge writes forever — configurable via\r\n`leaseMs` (default 10s):\r\n\r\n```ts\r\nconst storage = mongoDriver(db, { leaseMs: 5_000 });\r\n```\r\n\r\n## Catalog history and permission metrics\r\n\r\nThis driver keeps only the catalog head (no `AlfizCatalogVersion`\r\nequivalent), so the wildcard-drift report answers `unsupported` rather than\r\nwrongly. It also does not implement the optional rolling-metrics methods.\r\nBoth are OPTIONAL on `StorageDriver` — the Application detects their absence\r\nand refuses the corresponding feature at construction rather than accepting\r\ncalls that go nowhere.\r\n\r\n## Query safety\r\n\r\nNothing upstream of a storage driver validates the *runtime* type of an id\r\nor filter value — `@alfiz/application`'s Provider API checks field\r\npresence, not shape, so a JSON body carrying `{\"subject\": {\"$ne\": null}}`\r\nreaches the driver unmolested. Every value this driver assigns into a Mongo\r\nquery document — an id, or a filter field such as `subject`, `scope`,\r\n`roleId`, `actor` — is checked to be the expected primitive first and\r\nrejected with a `TypeError` otherwise, so an object-shaped value can never be\r\nread as a query operator instead of data.\r\n\r\n## What lives where\r\n\r\nThe driver stores and retrieves; it never interprets. All ids are opaque\r\nstrings assigned by the Application layer, which also owns graph integrity,\r\nrequest workflows, catalog versioning, and the audit log.\r\n","readmeFilename":"README.md"}