cvx-kit 0.1.8 → 0.1.11

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 (155) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +28 -28
  3. package/dist/agent-tools.d.mts +5 -5
  4. package/dist/agent-tools.mjs.map +1 -1
  5. package/dist/auth.d.mts +39 -289
  6. package/dist/auth.mjs.map +1 -1
  7. package/dist/components/approvals/_generated/api.d.mts +3 -4
  8. package/dist/components/approvals/_generated/api.mjs.map +1 -1
  9. package/dist/components/approvals/_generated/component.d.mts +1 -2
  10. package/dist/components/approvals/_generated/dataModel.d.mts +4 -5
  11. package/dist/components/approvals/_generated/server.d.mts +12 -13
  12. package/dist/components/approvals/_generated/server.mjs.map +1 -1
  13. package/dist/components/approvals/audit.d.mts +8 -8
  14. package/dist/components/approvals/audit.mjs +1 -1
  15. package/dist/components/approvals/audit.mjs.map +1 -1
  16. package/dist/components/approvals/client.d.mts +10 -10
  17. package/dist/components/approvals/client.mjs.map +1 -1
  18. package/dist/components/approvals/constants.d.mts +30 -30
  19. package/dist/components/approvals/constants.mjs.map +1 -1
  20. package/dist/components/approvals/convex.config.mjs.map +1 -1
  21. package/dist/components/approvals/decisions.d.mts +6 -6
  22. package/dist/components/approvals/decisions.mjs.map +1 -1
  23. package/dist/components/approvals/functions.d.mts +3 -3
  24. package/dist/components/approvals/functions.mjs.map +1 -1
  25. package/dist/components/approvals/health.d.mts +2 -2
  26. package/dist/components/approvals/health.mjs.map +1 -1
  27. package/dist/components/approvals/requests.d.mts +8 -8
  28. package/dist/components/approvals/requests.mjs.map +1 -1
  29. package/dist/components/approvals/validators.d.mts +29 -29
  30. package/dist/components/approvals/validators.mjs +1 -1
  31. package/dist/components/approvals/validators.mjs.map +1 -1
  32. package/dist/components/approvals/workflow.d.mts +3 -3
  33. package/dist/components/approvals/workflow.mjs.map +1 -1
  34. package/dist/components/approvals/workflow_steps.d.mts +15 -15
  35. package/dist/components/approvals/workflow_steps.mjs.map +1 -1
  36. package/dist/components/foundation/_generated/api.d.mts +3 -4
  37. package/dist/components/foundation/_generated/api.mjs.map +1 -1
  38. package/dist/components/foundation/_generated/component.d.mts +1 -2
  39. package/dist/components/foundation/_generated/dataModel.d.mts +4 -5
  40. package/dist/components/foundation/_generated/server.d.mts +12 -13
  41. package/dist/components/foundation/_generated/server.mjs.map +1 -1
  42. package/dist/components/foundation/client.d.mts +13 -13
  43. package/dist/components/foundation/client.mjs.map +1 -1
  44. package/dist/components/foundation/convex.config.mjs.map +1 -1
  45. package/dist/components/foundation/functions.d.mts +2 -2
  46. package/dist/components/foundation/functions.mjs.map +1 -1
  47. package/dist/components/foundation/modules/command/command.d.mts +14 -14
  48. package/dist/components/foundation/modules/command/command.mjs.map +1 -1
  49. package/dist/components/foundation/modules/command/lifecycle.d.mts +12 -13
  50. package/dist/components/foundation/modules/command/lifecycle.mjs.map +1 -1
  51. package/dist/components/foundation/modules/observability/observability.d.mts +4 -4
  52. package/dist/components/foundation/modules/observability/observability.mjs.map +1 -1
  53. package/dist/components/foundation/modules/query/query.d.mts +5 -5
  54. package/dist/components/foundation/modules/query/query.mjs.map +1 -1
  55. package/dist/components/foundation/operation.d.mts +5 -6
  56. package/dist/components/foundation/operation.mjs.map +1 -1
  57. package/dist/components/foundation/result.d.mts +6 -6
  58. package/dist/components/foundation/result.mjs.map +1 -1
  59. package/dist/components/foundation/telemetry.d.mts +2 -2
  60. package/dist/components/foundation/telemetry.mjs.map +1 -1
  61. package/dist/crud.d.mts +6 -5
  62. package/dist/crud.mjs.map +1 -1
  63. package/dist/effect.d.mts +3 -2
  64. package/dist/effect.mjs +1 -1
  65. package/dist/errors.d.mts +4 -4
  66. package/dist/errors.mjs.map +1 -1
  67. package/dist/index.d.mts +2 -2
  68. package/dist/middleware.d.mts +2 -3
  69. package/dist/middleware.mjs.map +1 -1
  70. package/dist/modules/contracts/contract.d.mts +12 -13
  71. package/dist/modules/contracts/contract.mjs.map +1 -1
  72. package/dist/modules/contracts/convex.d.mts +3 -5
  73. package/dist/modules/contracts/convex.mjs.map +1 -1
  74. package/dist/modules/contracts/errors.d.mts +8 -9
  75. package/dist/modules/contracts/errors.mjs +1 -1
  76. package/dist/modules/contracts/errors.mjs.map +1 -1
  77. package/dist/modules/contracts/exposure.d.mts +13 -14
  78. package/dist/modules/contracts/exposure.mjs +1 -1
  79. package/dist/modules/contracts/exposure.mjs.map +1 -1
  80. package/dist/modules/contracts/idempotency.d.mts +15 -16
  81. package/dist/modules/contracts/idempotency.mjs +1 -1
  82. package/dist/modules/contracts/idempotency.mjs.map +1 -1
  83. package/dist/modules/contracts/standard.d.mts +2 -3
  84. package/dist/modules/contracts/standard.mjs.map +1 -1
  85. package/dist/modules/contracts/workflow.d.mts +26 -27
  86. package/dist/modules/contracts/workflow.mjs.map +1 -1
  87. package/dist/modules/effect/api-runtime.d.mts +10 -11
  88. package/dist/modules/effect/api-runtime.mjs +1 -1
  89. package/dist/modules/effect/api-runtime.mjs.map +1 -1
  90. package/dist/modules/effect/api-zod.d.mts +2 -3
  91. package/dist/modules/effect/api-zod.mjs.map +1 -1
  92. package/dist/modules/effect/api.d.mts +4 -5
  93. package/dist/modules/effect/api.mjs.map +1 -1
  94. package/dist/modules/effect/auth.d.mts +43 -0
  95. package/dist/modules/effect/auth.mjs +2 -0
  96. package/dist/modules/effect/auth.mjs.map +1 -0
  97. package/dist/modules/effect/client.d.mts +1 -1
  98. package/dist/modules/effect/client.mjs +1 -1
  99. package/dist/modules/effect/command.d.mts +4 -5
  100. package/dist/modules/effect/command.mjs +1 -1
  101. package/dist/modules/effect/command.mjs.map +1 -1
  102. package/dist/modules/effect/crud.d.mts +7 -8
  103. package/dist/modules/effect/crud.mjs +1 -1
  104. package/dist/modules/effect/crud.mjs.map +1 -1
  105. package/dist/modules/effect/errors.d.mts +1 -2
  106. package/dist/modules/effect/errors.mjs.map +1 -1
  107. package/dist/modules/effect/foundation.d.mts +3 -4
  108. package/dist/modules/effect/foundation.mjs.map +1 -1
  109. package/dist/modules/effect/idempotency.d.mts +2 -3
  110. package/dist/modules/effect/idempotency.mjs.map +1 -1
  111. package/dist/modules/effect/normalize.d.mts +2 -3
  112. package/dist/modules/effect/normalize.mjs.map +1 -1
  113. package/dist/modules/effect/operation.d.mts +17 -18
  114. package/dist/modules/effect/operation.mjs.map +1 -1
  115. package/dist/modules/effect/query.d.mts +3 -4
  116. package/dist/modules/effect/query.mjs +1 -1
  117. package/dist/modules/effect/query.mjs.map +1 -1
  118. package/dist/modules/effect/schema.d.mts +8 -9
  119. package/dist/modules/effect/schema.mjs.map +1 -1
  120. package/dist/modules/effect/workflow.d.mts +5 -6
  121. package/dist/modules/effect/workflow.mjs +1 -1
  122. package/dist/modules/effect/workflow.mjs.map +1 -1
  123. package/dist/oxlint/architecture.d.mts +6 -7
  124. package/dist/oxlint/architecture.mjs +1 -1
  125. package/dist/oxlint/architecture.mjs.map +1 -1
  126. package/dist/oxlint/ast.d.mts +22 -23
  127. package/dist/oxlint/ast.mjs +1 -1
  128. package/dist/oxlint/ast.mjs.map +1 -1
  129. package/dist/oxlint/ownership.d.mts +2 -3
  130. package/dist/oxlint/ownership.mjs +1 -1
  131. package/dist/oxlint/ownership.mjs.map +1 -1
  132. package/dist/oxlint.d.mts +4 -4
  133. package/dist/oxlint.mjs +1 -1
  134. package/dist/oxlint.mjs.map +1 -1
  135. package/dist/state-machine.d.mts +1 -2
  136. package/dist/state-machine.mjs.map +1 -1
  137. package/dist/tenancy.d.mts +6 -6
  138. package/dist/tenancy.mjs.map +1 -1
  139. package/dist/triggers.d.mts +6 -6
  140. package/dist/triggers.mjs.map +1 -1
  141. package/dist/webhooks.d.mts +5 -6
  142. package/dist/webhooks.mjs.map +1 -1
  143. package/dist/zod-table.d.mts +10 -10
  144. package/dist/zod-table.mjs.map +1 -1
  145. package/docs/auth.md +131 -1
  146. package/docs/effect.md +8 -2
  147. package/docs/llms.md +41 -20
  148. package/docs/oxlint.md +1 -1
  149. package/docs/upgrading.md +9 -1
  150. package/docs/zod-table.md +1 -1
  151. package/package.json +21 -15
  152. package/scripts/test-packed-auth.mjs +72 -0
  153. package/scripts/test-packed-effect.mjs +2 -1
  154. package/scripts/test-packed-ids.mjs +2 -2
  155. package/dist/node_modules/@standard-schema/spec/dist/index.d.mts +0 -79
package/docs/auth.md CHANGED
@@ -64,9 +64,139 @@ export const {
64
64
  Every function in the app is then built from these — raw `query`/`mutation`
65
65
  imports from `_generated/server` appear **only** in this file.
66
66
 
67
+ ## One shared Effect function foundation
68
+
69
+ Use `createEffectAuthFunctions` from `cvx-kit/effect` in `convex/functions.ts`
70
+ to configure all twelve constructors once. Its first argument is the same
71
+ `AuthFunctionsConfig` used by `createAuthFunctions`; its second argument has
72
+ six explicit policies: `query`, `mutation`, `action`, `systemQuery`,
73
+ `systemMutation`, and `systemAction`. Each accepts `services`, `context`, and
74
+ `mapError`, like `effectZodApiBuilder`. Pass `{}` when no additions are needed.
75
+
76
+ Type the auth config with your generated `DataModel` and role vocabulary,
77
+ then let the factory infer its generics from both arguments. Do not supply
78
+ partial generic arguments, which would fix the remaining inference defaults.
79
+ The following public-package example defines a reusable app factory; the
80
+ host passes its auth, membership, trigger, and RLS policy as `config`.
81
+
82
+ <!-- packed-effect-example -->
83
+
84
+ ```ts
85
+ import {
86
+ defineSchema,
87
+ defineTable,
88
+ makeFunctionReference,
89
+ type DataModelFromSchemaDefinition,
90
+ type GenericQueryCtx,
91
+ type GenericMutationCtx,
92
+ } from 'convex/server'
93
+ import { v } from 'convex/values'
94
+ import { Effect } from 'effect'
95
+ import { z } from 'zod'
96
+ import type { AuthFunctionsConfig, AuthBundle } from 'cvx-kit/auth'
97
+ import { createEffectAuthFunctions, createEffectFoundation } from 'cvx-kit/effect'
98
+
99
+ const schema = defineSchema({ notes: defineTable({ tenant: v.string(), title: v.string() }) })
100
+ type Model = DataModelFromSchemaDefinition<typeof schema>
101
+ type Role = 'owner' | 'viewer'
102
+ const input = z.object({ title: z.string().trim().min(1) })
103
+ const saveRef = makeFunctionReference<'mutation', z.input<typeof input>, null>('notes:save')
104
+
105
+ export function createApplicationFunctions(config: AuthFunctionsConfig<Model, Role>) {
106
+ const foundation = createEffectFoundation({
107
+ observability: {
108
+ enabled: false,
109
+ classifyError: () => ({ outcome: 'failed', errorCode: 'FAILED' }),
110
+ },
111
+ writeAudit: () => undefined, // supply the app's transactional audit writer in production
112
+ })
113
+ const queries = foundation.Query({
114
+ context: (ctx: (GenericQueryCtx<Model> | GenericMutationCtx<Model>) & AuthBundle<Role>) => ctx,
115
+ operations: ({ query }) => ({
116
+ actor: query({
117
+ input: z.object({}),
118
+ result: z.string(),
119
+ handler: (_input, ctx) => ctx.actor.userId,
120
+ }),
121
+ }),
122
+ })
123
+ const commands = foundation.Command({
124
+ context: (ctx: GenericMutationCtx<Model> & AuthBundle<Role>) => ctx,
125
+ operations: ({ command }) => ({
126
+ save: command({
127
+ input,
128
+ result: z.null(),
129
+ classification: 'business',
130
+ audit: () => null,
131
+ handler: (args, ctx) =>
132
+ Effect.promise(async () => {
133
+ await ctx.db.insert('notes', { title: args.title, tenant: ctx.tenant })
134
+ return null
135
+ }),
136
+ }),
137
+ }),
138
+ })
139
+ const functions = createEffectAuthFunctions(config, {
140
+ query: { context: (ctx) => ({ queries: queries.withContext(ctx) }) },
141
+ mutation: {
142
+ context: (ctx) => ({
143
+ queries: queries.withContext(ctx),
144
+ commands: commands.withContext(ctx),
145
+ }),
146
+ },
147
+ action: {
148
+ context: (ctx) => ({
149
+ commands: {
150
+ save: (args: z.input<typeof input>) =>
151
+ Effect.promise(() => ctx.runMutation(saveRef, args)),
152
+ },
153
+ }),
154
+ },
155
+ systemQuery: {},
156
+ systemMutation: {},
157
+ systemAction: {},
158
+ })
159
+ const save = functions.roleMutation('owner')({
160
+ args: input.shape,
161
+ returns: z.null(),
162
+ handler: (ctx, args) => ctx.commands.exec('save', args),
163
+ })
164
+ return { ...functions, save }
165
+ }
166
+ ```
167
+
168
+ Export the returned constructors once from `convex/functions.ts`, and export
169
+ `save` at the registered `notes:save` mutation path. Endpoint modules can then
170
+ use `ctx.commands` or `ctx.queries` directly. The callbacks run per invocation
171
+ after auth, role checks, triggers/RLS wrapping, and live action membership
172
+ refresh. Binding is lazy; do not cache an authenticated `withContext` handle
173
+ at module scope. Denied requests never run the callbacks.
174
+
175
+ | Policy | Available authority and capabilities |
176
+ | ------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
177
+ | `query` | Trusted auth bundle, secured DB reader, `include`; bind read registries only. |
178
+ | `mutation` | Trusted auth bundle, secured triggered DB writer, `include`; bind queries and mutation commands. |
179
+ | `action` | Live-verified auth bundle, `runQuery`/`runMutation`; use action-compatible registries or forward to registered functions. No DB or `include`. |
180
+ | `systemQuery` / `systemMutation` / `systemAction` | Existing internal authority, configured separately. No fabricated actor or inherited public handles; system mutations retain triggers and bypass public RLS as before. |
181
+
182
+ Every auth/role/admin constructor of a kind shares that kind's policy. System
183
+ policies are deliberately explicit; choose their trusted capabilities rather
184
+ than synthesizing public credentials. An action forwarding to `runMutation`
185
+ creates a separate registered mutation transaction; it does not turn the
186
+ whole action into a transaction or carry its live role into that mutation's
187
+ JWT-based auth policy.
188
+
189
+ Additions cannot replace native or auth context keys: static checks reject
190
+ known collisions and runtime checks also reject inherited keys before the
191
+ handler executes. Put class-based handles under named properties in the
192
+ returned plain record. Scoped services, required Effect services, Zod raw and
193
+ parsed argument/result types, function references, and error projection retain
194
+ the existing adapter's behavior. Let failures escape registered mutations so
195
+ nested command writes, triggers, and audit writes roll back together.
196
+
67
197
  ## Shared Effect execution after authentication
68
198
 
69
- Wrap the constructors returned by `createAuthFunctions` with
199
+ For an individual constructor, wrap the builder returned by `createAuthFunctions` with
70
200
  `effectZodApiBuilder` from `cvx-kit/effect`. The original constructor resolves
71
201
  authentication, authorization, tenant policy, and the wrapped database before
72
202
  the service provider runs. Keep that ordering when adding Effect; use the Zod
package/docs/effect.md CHANGED
@@ -384,11 +384,17 @@ only when you want a typed error channel.
384
384
  The [command guide](./commands.md) documents the current lifecycle and migration
385
385
  steps; the [deprecated API reference](./commands-legacy.md) retains old examples.
386
386
  The [authentication guide](./auth.md)
387
- shows how to wrap trusted custom builders with `effectZodApiBuilder`, so auth,
387
+ shows the shared `createEffectAuthFunctions(config, policies)` factory and how
388
+ to wrap individual trusted builders with `effectZodApiBuilder`, so auth,
388
389
  tenancy, validators, row-level policies, and triggers run through their
389
390
  existing builder before Effect request services are provisioned.
390
391
 
391
- Optional request context can be added through the existing Effect API adapter's
392
+ For an app-wide foundation, configure `query`, `mutation`, and `action` policies
393
+ once with `createEffectAuthFunctions` and explicit separate system policies.
394
+ Query handles bind readers, mutation handles bind the secured triggered writer,
395
+ and action handles use `runMutation` rather than a mutation database.
396
+
397
+ Optional request context can also be added through the existing Effect API adapter's
392
398
  `context` callback. Bind selected registries with `commands.withContext(value)`
393
399
  and consume `ctx.commands.exec(name, input)` through the application's existing
394
400
  function helper names. Keep dependencies local to each feature; explicit execution
package/docs/llms.md CHANGED
@@ -22,7 +22,7 @@
22
22
  cvx-kit is a reusable Convex application kit: zod table boundaries, auth-aware
23
23
  function constructors, a trigger registry, an audited command protocol
24
24
  (Foundation component), and a declarative approvals component. Peer deps:
25
- `convex ^1.45.0`, `zod ^4.5.4`; command implementations also install
25
+ `convex ^1.46.0`, `zod ^4.5.4`; command implementations also install
26
26
  `effect >=4.0.1 <5` and import `cvx-kit/effect`.
27
27
 
28
28
  **Command API selection:** use `createEffectFoundation` and declare handlers
@@ -38,12 +38,13 @@ copy that API into new implementations.
38
38
  `convex/functions.ts`** (the `createAuthFunctions` call). All other
39
39
  functions use `authQuery/authMutation/authAction`, `roleQuery/...`,
40
40
  `adminQuery/...` (public) or `systemQuery/systemMutation/systemAction` (internal),
41
- wrapped once with `effectZodApiBuilder` when their handlers return Effects.
41
+ built once with `createEffectAuthFunctions(config, policies)` from `cvx-kit/effect`
42
+ for shared Effect handles, or individually wrapped with `effectZodApiBuilder`.
42
43
  This is what guarantees auth, triggers, and bounded reads.
43
44
  3. **Every public query returns DTOs** via `<table>.toPublicDto(row)` —
44
45
  runtime redaction, not just types.
45
46
  4. **Every read is bounded**: `ctx.include(ctx.db.query('t')).matching(...)
46
- .execute(limit)` with `1 ≤ limit ≤ 100`. `.resolve()` falls back to a full
47
+ .execute(limit)` with `1 ≤ limit ≤ 100`. `.resolve()` falls back to a full
47
48
  table scan — avoid it.
48
49
  5. **State changes are Effect commands**: declare
49
50
  `Command({ context, operations: ({ command }) => ({ ... }), defaults })`.
@@ -78,23 +79,23 @@ copy that API into new implementations.
78
79
 
79
80
  ## Exports map
80
81
 
81
- | Import | Provides |
82
- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
83
- | `cvx-kit` | Non-Effect helpers and component clients; import the optional Effect facade explicitly from `cvx-kit/effect`. |
84
- | `cvx-kit/zod-table` | `zodTable`, `tenantTable`, `createModule`, `paginated`, `zodVariantTable`, `jsonSafeZid`, `TIMESTAMP_FIELDS` |
85
- | `cvx-kit/effect` | Recommended command/query API: `createEffectFoundation`, `effectApiBuilder`, `effectZodApiBuilder`, `createEffectCrud`, idempotency/workflow adapters and operation tools. |
86
- | `cvx-kit/auth` | `createAuthFunctions` (incl. optional `security` RLS config), `createInclude`, `defaultRoleMap` |
87
- | `cvx-kit/tenancy` | `createTenantRules`, `composeRules`, `requireTenantReference`, `assertTenantOwned`, `TENANT_FIELD` |
88
- | `cvx-kit/crud` | Compatibility CRUD factory using the deprecated Promise command facade; use `createEffectCrud` from `cvx-kit/effect` for new domains. |
89
- | `cvx-kit/state-machine` | `createStateMachine` — typed transitions from constants tuples; `assert` drops into command guards |
90
- | `cvx-kit/middleware` | `rateLimit` — packaged middleware over an injected rate-limiter instance; keyed by `ctx.tenant`, missing key = config error |
91
- | `cvx-kit/webhooks` | `createWebhookBoundary`, `recordWebhookEvent`, `webhookEventsTable` — raw-body verify, natural-key dedup in the mutation |
92
- | `cvx-kit/agent-tools` | `createAgentTools` — tool records from table masks; mutation handlers route through command executors |
93
- | `cvx-kit/triggers` | `createTriggers`, `timestamps`, `appendOnly`, `noDelete`, `tenantOwnership`, `Triggers` |
94
- | `cvx-kit/errors` | `KitError`, `defaultErrors`, `ErrorFactory` |
95
- | `cvx-kit/components/foundation` | Component client and types; `Foundation.Command` is deprecated. The component and other capabilities remain available. New command registries use `cvx-kit/effect`. |
96
- | `cvx-kit/components/approvals` | `Approvals` client; default export = component config for `app.use` |
97
- | `cvx-kit/test` | `registerFoundation(t)`, `registerApprovals(t)` for convex-test |
82
+ | Import | Provides |
83
+ | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
84
+ | `cvx-kit` | Non-Effect helpers and component clients; import the optional Effect facade explicitly from `cvx-kit/effect`. |
85
+ | `cvx-kit/zod-table` | `zodTable`, `tenantTable`, `createModule`, `paginated`, `zodVariantTable`, `jsonSafeZid`, `TIMESTAMP_FIELDS` |
86
+ | `cvx-kit/effect` | Recommended command/query API: `createEffectFoundation`, `createEffectAuthFunctions`, `effectApiBuilder`, `effectZodApiBuilder`, `createEffectCrud`, idempotency/workflow adapters and operation tools. |
87
+ | `cvx-kit/auth` | `createAuthFunctions` (incl. optional `security` RLS config), `createInclude`, `defaultRoleMap` |
88
+ | `cvx-kit/tenancy` | `createTenantRules`, `composeRules`, `requireTenantReference`, `assertTenantOwned`, `TENANT_FIELD` |
89
+ | `cvx-kit/crud` | Compatibility CRUD factory using the deprecated Promise command facade; use `createEffectCrud` from `cvx-kit/effect` for new domains. |
90
+ | `cvx-kit/state-machine` | `createStateMachine` — typed transitions from constants tuples; `assert` drops into command guards |
91
+ | `cvx-kit/middleware` | `rateLimit` — packaged middleware over an injected rate-limiter instance; keyed by `ctx.tenant`, missing key = config error |
92
+ | `cvx-kit/webhooks` | `createWebhookBoundary`, `recordWebhookEvent`, `webhookEventsTable` — raw-body verify, natural-key dedup in the mutation |
93
+ | `cvx-kit/agent-tools` | `createAgentTools` — tool records from table masks; mutation handlers route through command executors |
94
+ | `cvx-kit/triggers` | `createTriggers`, `timestamps`, `appendOnly`, `noDelete`, `tenantOwnership`, `Triggers` |
95
+ | `cvx-kit/errors` | `KitError`, `defaultErrors`, `ErrorFactory` |
96
+ | `cvx-kit/components/foundation` | Component client and types; `Foundation.Command` is deprecated. The component and other capabilities remain available. New command registries use `cvx-kit/effect`. |
97
+ | `cvx-kit/components/approvals` | `Approvals` client; default export = component config for `app.use` |
98
+ | `cvx-kit/test` | `registerFoundation(t)`, `registerApprovals(t)` for convex-test |
98
99
 
99
100
  ## Minimal app wiring (the five root files)
100
101
 
@@ -291,3 +292,23 @@ Optional request context can be added through the existing Effect API adapter's
291
292
  and consume `ctx.commands.exec(name, input)` through the application's existing
292
293
  function helper names. Keep dependencies local to each feature; explicit execution
293
294
  and input-only command handlers remain supported. See [optional context injection](./command-context.md).
295
+
296
+ ## Shared auth and Effect context
297
+
298
+ Configure `createEffectAuthFunctions` once in `convex/functions.ts` using a typed
299
+ `AuthFunctionsConfig<DataModel, Role>` and inferred factory generics. Supply six
300
+ explicit policies: `query`, `mutation`, `action`, `systemQuery`, `systemMutation`,
301
+ and `systemAction`; use `{}` for no additions. Each supports `services`,
302
+ `context`, and `mapError`. All auth/role/admin constructors share the policy
303
+ for their kind. Services and context initialize only after successful auth and
304
+ role checks, using the secured DB and refreshed live action membership.
305
+
306
+ Bind query registries only in queries. Mutations can bind queries and commands
307
+ with their secured triggered writer. Actions have no DB; bind action-compatible
308
+ registries or delegate with `runMutation`/`runQuery`. Each registered mutation
309
+ has its own transaction and JWT auth; an action is not one transaction. Configure
310
+ internal system authority separately, without fabricated actors or inherited
311
+ public handles. Return plain records with handles under named keys; native/auth
312
+ key collisions are rejected, including inherited keys at runtime. Keep bound
313
+ handles request-local, return lazy Effects, and let failures escape mutations
314
+ for rollback. See `auth.md` for a packed-compiled shared factory example.
package/docs/oxlint.md CHANGED
@@ -27,7 +27,7 @@ Loading a plugin does not enable its rules. For example:
27
27
 
28
28
  With Vite+, place those fields under `lint` in `vite.config.ts`. The plugin
29
29
  exports a default plugin object, named `rules`, and the `RuleName` type. It is
30
- tested with Oxlint 1.79.0 and Vite+ 0.3.0.
30
+ tested with Oxlint 1.87.0 and Vite+ 1.1.0.
31
31
 
32
32
  All rules default to `convex/` relative to the linter's working directory.
33
33
  For another location, set `convexDir` on **each enabled rule**:
package/docs/upgrading.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Upgrading to 0.1.0 — the new way of things
2
2
 
3
+ ## Current dependency requirements
4
+
5
+ Install Convex 1.46 or newer and convex-helpers 0.1.127 or newer (below 0.2.0).
6
+ These minimums match workflow 0.4.10. Regenerate your lockfile after updating.
7
+ Auth declarations retain native Convex context types across package versions;
8
+ the regression fixture also checks Convex 1.45, which is below the current
9
+ full-package dependency minimum.
10
+
3
11
  ## Current command API — Effect declarations
4
12
 
5
13
  `Foundation.Command` and its separate `exec({ operation, handler })` API are
@@ -67,7 +75,7 @@ Install `convex-helpers` as a direct peer, using one compatible instance:
67
75
  bun add cvx-kit@0.1.3 convex-helpers@0.1.124
68
76
  ```
69
77
 
70
- The peer range is `>=0.1.123 <0.2.0`. Remove overrides that force a
78
+ The peer range was `>=0.1.123 <0.2.0`. Remove overrides that force a
71
79
  separate helper copy and regenerate the installation without discarding
72
80
  unrelated dependency choices. This release is validated with Convex 1.45.0,
73
81
  Zod 4.5.4, and convex-test 0.0.56.
package/docs/zod-table.md CHANGED
@@ -29,7 +29,7 @@ export const documents = zodTable(
29
29
 
30
30
  ### Shared ID validation (0.1.3)
31
31
 
32
- Install one compatible `convex-helpers` peer (`>=0.1.123 <0.2.0`) alongside
32
+ Install one compatible `convex-helpers` peer (`>=0.1.127 <0.2.0`) alongside
33
33
  cvx-kit. ID metadata lives in a helper-instance registry: copying schemas
34
34
  between separately installed helper instances can silently turn an ID into
35
35
  `v.any()`. An exact nested dependency previously caused that failure even
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cvx-kit",
3
- "version": "0.1.8",
3
+ "version": "0.1.11",
4
4
  "description": "Reusable Convex application kit: foundation kernels, approvals component, zod table boundaries, WorkOS-backed auth function constructors, and audited command protocol.",
5
5
  "keywords": [
6
6
  "component",
@@ -133,6 +133,7 @@
133
133
  "test:package:ids": "bun run build && node scripts/test-packed-ids.mjs",
134
134
  "test:package:oxlint": "bun run build && node scripts/test-packed-oxlint.mjs",
135
135
  "test:package:effect": "bun run build && node scripts/test-packed-effect.mjs",
136
+ "test:package:auth": "bun run build && node scripts/test-packed-auth.mjs",
136
137
  "test:package:smoke:effect": "bun run build && node scripts/smoke-packed-effect.mjs",
137
138
  "test:package:smoke:bun": "bun scripts/smoke-packed-components.mjs bun",
138
139
  "test:package:smoke:npm": "node scripts/smoke-packed-components.mjs npm",
@@ -143,28 +144,30 @@
143
144
  "release:minor": "npm version minor && git push --follow-tags"
144
145
  },
145
146
  "dependencies": {
146
- "@convex-dev/workflow": "0.4.6",
147
- "@oxlint/plugins": "1.79.0",
147
+ "@convex-dev/workflow": "0.4.10",
148
+ "@oxlint/plugins": "1.87.0",
149
+ "@standard-schema/spec": "^1.1.0",
148
150
  "convex-audit-log": "^0.2.0",
149
- "oxc-parser": "0.150.0",
151
+ "oxc-parser": "0.153.0",
150
152
  "oxc-resolver": "11.24.2"
151
153
  },
152
154
  "devDependencies": {
153
155
  "@edge-runtime/vm": "^5.0.0",
154
- "@types/node": "^26.6.1",
155
- "convex": "1.45.0",
156
- "convex-helpers": "0.1.124",
157
- "convex-test": "^0.0.56",
158
- "effect": "4.0.1",
159
- "oxlint": "1.79.0",
160
- "publint": "^0.3.24",
156
+ "@types/node": "^26.6.5",
157
+ "convex": "1.46.0",
158
+ "convex-helpers": "0.1.128",
159
+ "convex-test": "^0.0.61",
160
+ "effect": "4.0.2",
161
+ "oxlint": "1.87.0",
162
+ "publint": "^0.3.25",
161
163
  "typescript": "7.0.2",
162
- "vite-plus": "0.3.0",
163
- "zod": "4.5.4"
164
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0",
165
+ "vite-plus": "1.1.0",
166
+ "zod": "4.6.5"
164
167
  },
165
168
  "peerDependencies": {
166
- "convex": "^1.45.0",
167
- "convex-helpers": ">=0.1.123 <0.2.0",
169
+ "convex": "^1.46.0",
170
+ "convex-helpers": ">=0.1.127 <0.2.0",
168
171
  "effect": ">=4.0.1 <5",
169
172
  "zod": "^4.5.4"
170
173
  },
@@ -173,6 +176,9 @@
173
176
  "optional": true
174
177
  }
175
178
  },
179
+ "overrides": {
180
+ "vite": "npm:@voidzero-dev/vite-plus-core@1.1.0"
181
+ },
176
182
  "devEngines": {
177
183
  "packageManager": {
178
184
  "name": "bun",
@@ -0,0 +1,72 @@
1
+ import { execFileSync } from 'node:child_process'
2
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
3
+ import { tmpdir } from 'node:os'
4
+ import { basename, join, resolve } from 'node:path'
5
+
6
+ const root = resolve(import.meta.dirname, '..')
7
+ const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
8
+ const temporary = mkdtempSync(join(tmpdir(), 'cvx-kit-auth-'))
9
+ function run(command, args, cwd) {
10
+ try {
11
+ return execFileSync(command, args, { cwd, encoding: 'utf8', stdio: 'pipe' })
12
+ } catch (error) {
13
+ if (!args.includes('install')) {
14
+ process.stderr.write(error.stdout ?? '')
15
+ process.stderr.write(error.stderr ?? '')
16
+ }
17
+ throw new Error(`${command} ${args.join(' ')} failed in ${basename(cwd)}`, {
18
+ cause: error.code,
19
+ })
20
+ }
21
+ }
22
+ try {
23
+ run('bun', ['pm', 'pack', '--ignore-scripts', '--destination', temporary], root)
24
+ const tarball = join(temporary, `${manifest.name}-${manifest.version}.tgz`)
25
+ // 1.45 is a declaration regression target, below the current workflow peer floor.
26
+ for (const convex of ['1.45.0', '1.46.0']) {
27
+ const fixture = mkdtempSync(join(temporary, `convex-${convex}-`))
28
+ writeFileSync(
29
+ join(fixture, 'package.json'),
30
+ JSON.stringify({
31
+ private: true,
32
+ type: 'module',
33
+ dependencies: {
34
+ 'cvx-kit': `file:${tarball}`,
35
+ convex,
36
+ 'convex-helpers': manifest.devDependencies['convex-helpers'],
37
+ effect: manifest.devDependencies.effect,
38
+ zod: manifest.devDependencies.zod,
39
+ typescript: manifest.devDependencies.typescript,
40
+ '@types/node': manifest.devDependencies['@types/node'],
41
+ },
42
+ }),
43
+ )
44
+ writeFileSync(
45
+ join(fixture, 'auth.ts'),
46
+ readFileSync(join(root, 'test/auth-native-context-types.ts')),
47
+ )
48
+ writeFileSync(
49
+ join(fixture, 'shared-auth.ts'),
50
+ readFileSync(join(root, 'test/effect-auth-types.ts')),
51
+ )
52
+ writeFileSync(
53
+ join(fixture, 'tsconfig.json'),
54
+ JSON.stringify({
55
+ compilerOptions: {
56
+ strict: true,
57
+ noEmit: true,
58
+ skipLibCheck: true,
59
+ target: 'ES2025',
60
+ module: 'ESNext',
61
+ moduleResolution: 'bundler',
62
+ },
63
+ include: ['auth.ts', 'shared-auth.ts'],
64
+ }),
65
+ )
66
+ run('bun', ['install', '--ignore-scripts'], fixture)
67
+ run('bun', ['x', '--no-install', 'tsc', '--project', 'tsconfig.json'], fixture)
68
+ console.log(`Packed auth native contexts pass on Convex ${convex}`)
69
+ }
70
+ } finally {
71
+ rmSync(temporary, { recursive: true, force: true })
72
+ }
@@ -15,7 +15,7 @@ const root = resolve(import.meta.dirname, '..')
15
15
  const manifest = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'))
16
16
  const temporary = mkdtempSync(join(tmpdir(), 'cvx-kit-effect-'))
17
17
  const effectVersion = '4.0.1'
18
- const helpersVersion = '0.1.123'
18
+ const helpersVersion = '0.1.127'
19
19
  const nodeTypesVersion = '26.6.1'
20
20
  const domainGuidePath = join(root, 'src/docs/domain-operations.md')
21
21
  const domainGuideImports = new Set([
@@ -396,6 +396,7 @@ try {
396
396
  'effect-foundation-types.ts',
397
397
  'effect-api-types.ts',
398
398
  'effect-api-zod-types.ts',
399
+ 'effect-auth-types.ts',
399
400
  'effect-registry-review-types.ts',
400
401
  'operation-contract-types.ts',
401
402
  'effect-schema-types.ts',
@@ -25,7 +25,7 @@ try {
25
25
  type: 'module',
26
26
  dependencies: {
27
27
  'cvx-kit': `file:${join(temporary, `cvx-kit-${manifest.version}.tgz`)}`,
28
- 'convex-helpers': '0.1.123',
28
+ 'convex-helpers': '0.1.127',
29
29
  convex: manifest.devDependencies.convex,
30
30
  zod: manifest.devDependencies.zod,
31
31
  },
@@ -142,7 +142,7 @@ it('registers concrete and generic backends from the packed package', () => {
142
142
  fixture,
143
143
  )
144
144
  console.log(
145
- `${installer}: packed IDs, table/tool types, registration, and command lifecycle pass with host convex-helpers 0.1.123`,
145
+ `${installer}: packed IDs, table/tool types, registration, and command lifecycle pass with host convex-helpers 0.1.127`,
146
146
  )
147
147
  }
148
148
  } finally {
@@ -1,79 +0,0 @@
1
- //#region node_modules/@standard-schema/spec/dist/index.d.ts
2
- /** The Standard Typed interface. This is a base type extended by other specs. */
3
- interface StandardTypedV1<Input = unknown, Output = Input> {
4
- /** The Standard properties. */
5
- readonly "~standard": StandardTypedV1.Props<Input, Output>;
6
- }
7
- declare namespace StandardTypedV1 {
8
- /** The Standard Typed properties interface. */
9
- interface Props<Input = unknown, Output = Input> {
10
- /** The version number of the standard. */
11
- readonly version: 1;
12
- /** The vendor name of the schema library. */
13
- readonly vendor: string;
14
- /** Inferred types associated with the schema. */
15
- readonly types?: Types<Input, Output> | undefined;
16
- }
17
- /** The Standard Typed types interface. */
18
- interface Types<Input = unknown, Output = Input> {
19
- /** The input type of the schema. */
20
- readonly input: Input;
21
- /** The output type of the schema. */
22
- readonly output: Output;
23
- }
24
- /** Infers the input type of a Standard Typed. */
25
- type InferInput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["input"];
26
- /** Infers the output type of a Standard Typed. */
27
- type InferOutput<Schema extends StandardTypedV1> = NonNullable<Schema["~standard"]["types"]>["output"];
28
- }
29
- /** The Standard Schema interface. */
30
- interface StandardSchemaV1<Input = unknown, Output = Input> {
31
- /** The Standard Schema properties. */
32
- readonly "~standard": StandardSchemaV1.Props<Input, Output>;
33
- }
34
- declare namespace StandardSchemaV1 {
35
- /** The Standard Schema properties interface. */
36
- interface Props<Input = unknown, Output = Input> extends StandardTypedV1.Props<Input, Output> {
37
- /** Validates unknown input values. */
38
- readonly validate: (value: unknown, options?: StandardSchemaV1.Options | undefined) => Result<Output> | Promise<Result<Output>>;
39
- }
40
- /** The result interface of the validate function. */
41
- type Result<Output> = SuccessResult<Output> | FailureResult;
42
- /** The result interface if validation succeeds. */
43
- interface SuccessResult<Output> {
44
- /** The typed output value. */
45
- readonly value: Output;
46
- /** A falsy value for `issues` indicates success. */
47
- readonly issues?: undefined;
48
- }
49
- interface Options {
50
- /** Explicit support for additional vendor-specific parameters, if needed. */
51
- readonly libraryOptions?: Record<string, unknown> | undefined;
52
- }
53
- /** The result interface if validation fails. */
54
- interface FailureResult {
55
- /** The issues of failed validation. */
56
- readonly issues: ReadonlyArray<Issue>;
57
- }
58
- /** The issue interface of the failure output. */
59
- interface Issue {
60
- /** The error message of the issue. */
61
- readonly message: string;
62
- /** The path of the issue, if any. */
63
- readonly path?: ReadonlyArray<PropertyKey | PathSegment> | undefined;
64
- }
65
- /** The path segment interface of the issue. */
66
- interface PathSegment {
67
- /** The key representing a path segment. */
68
- readonly key: PropertyKey;
69
- }
70
- /** The Standard types interface. */
71
- interface Types<Input = unknown, Output = Input> extends StandardTypedV1.Types<Input, Output> {}
72
- /** Infers the input type of a Standard. */
73
- type InferInput<Schema extends StandardTypedV1> = StandardTypedV1.InferInput<Schema>;
74
- /** Infers the output type of a Standard. */
75
- type InferOutput<Schema extends StandardTypedV1> = StandardTypedV1.InferOutput<Schema>;
76
- }
77
- //#endregion
78
- export { StandardSchemaV1, StandardTypedV1 };
79
- //# sourceMappingURL=index.d.mts.map