@lunora/server 1.0.0-alpha.10 → 1.0.0-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +74 -4
- package/dist/index.d.ts +74 -4
- package/dist/index.mjs +4 -3
- package/dist/packem_shared/{buildRlsReadRegistry-1jexWrb3.mjs → buildRlsReadRegistry-Do1CSBTr.mjs} +1 -1
- package/dist/packem_shared/defineIdentity-B_9YD46A.mjs +34 -0
- package/dist/packem_shared/{mask-BV_jNzsN.mjs → mask-CWfMjb5Y.mjs} +46 -1
- package/dist/packem_shared/{rls-2Jhd0uev.mjs → rls-DhNgKFeW.mjs} +6 -3
- package/dist/packem_shared/{types.d-DmvyEMD6.d.mts → types.d-BB3pjV0m.d.mts} +10 -4
- package/dist/packem_shared/{types.d-BDY0FYHK.d.ts → types.d-Cxl6ndhm.d.ts} +10 -4
- package/dist/rls/testing.d.mts +1 -1
- package/dist/rls/testing.d.ts +1 -1
- package/dist/rls/testing.mjs +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -3,8 +3,8 @@ export { type ColumnValidator, type Id, type Infer, ValidationError, type Valida
|
|
|
3
3
|
import { ArgsValidator, InferArgs, RegisteredAction, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, RegisteredStream, FunctionKind, Secrets, LifecycleEvent, RegisteredLifecycleHook, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, DurableObjectJurisdiction, RelationDefinition, GlobalBackend, OnDeleteAction, ExternalSourceDefinition, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, AggregateIndexDefinition, RankIndexDefinition } from "./types.mjs";
|
|
4
4
|
export { type AnyApi, type AuthState, type DatabaseReader, type DatabaseWriter, type FunctionVisibility, type IndexDefinition, type IndexRangeBuilder, type LifecycleEventKind, type LunoraLogger, type PaginationOptions, type PaginationResult, type RankSortKey, type ReadOnlyStorage, type ScheduledFunctionDoc, type ScheduledJob, type Scheduler, type SearchFilterBuilder, type SearchIndexDefinition, type ShardMode, type Storage, type StorageMetadata, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemTableName, type TableReader, type TableVectorIndex, type TriggerAggregateOptions, type TriggerCtx, type TriggerDatabase, type TriggerDeleteEvent, type TriggerEvent, type TriggerGroupByEntry, type TriggerGroupByOptions, type TriggerHandler, type TriggerInsertEvent, type TriggerOp, type TriggerQueryArgs, type TriggerQueryPage, type TriggerRankOptions, type TriggerRankPageOptions, type TriggerRankResult, type TriggerRow, type TriggerTiming, type TriggerUpdateEvent, type VectorMatch, type VectorMatches, type VectorQueryInput, type VectorRecord, type VectorSearch, type VectorSearchReader, type VectorUpsertInput, type WorkflowCreateOptions, type WorkflowHandle, type WorkflowInstance, type WorkflowInstanceStatus, type WorkflowStatusResult, type Workflows, anyApi } from "./types.mjs";
|
|
5
5
|
import { Context, Hono } from 'hono';
|
|
6
|
-
import { b as Permission, R as Role, T as TypedDefinePolicyInput, a as Policy, D as DefinePolicyInput, W as WhereInput, c as RlsOptions } from "./packem_shared/types.d-
|
|
7
|
-
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-
|
|
6
|
+
import { b as Permission, R as Role, T as TypedDefinePolicyInput, a as Policy, D as DefinePolicyInput, W as WhereInput, c as RlsOptions } from "./packem_shared/types.d-BB3pjV0m.mjs";
|
|
7
|
+
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-BB3pjV0m.mjs";
|
|
8
8
|
export { type CronJob, type CronJobsBuilder, type CronScheduleKind, type DailySchedule, type IntervalSchedule, type MonthlySchedule, type WeeklySchedule, cronJobs } from '@lunora/scheduler';
|
|
9
9
|
import "./data-model.mjs";
|
|
10
10
|
/**
|
|
@@ -674,6 +674,76 @@ interface ContextWithStorage {
|
|
|
674
674
|
* client then ranges against R2/CDN directly with no Worker hop.
|
|
675
675
|
*/
|
|
676
676
|
declare const serveStorageObject: (context: ContextWithStorage, key: string, request: Request) => Promise<Response>;
|
|
677
|
+
/**
|
|
678
|
+
* What the worker does with a resolver's identity when it fails contract
|
|
679
|
+
* validation (a forged / malformed claim set arriving from an untrusted token).
|
|
680
|
+
* `"anonymous"` (default, safe) treats the request as anonymous, so the bad
|
|
681
|
+
* identity never reaches a policy as a valid identity (`ctx.auth.userId`
|
|
682
|
+
* becomes `undefined`). `"reject"` fails the request closed (a `401`) — use
|
|
683
|
+
* when a malformed credential should be a hard error, not a silent downgrade.
|
|
684
|
+
*/
|
|
685
|
+
type IdentityRejectMode = "anonymous" | "reject";
|
|
686
|
+
/** Options for {@link defineIdentity}. */
|
|
687
|
+
interface DefineIdentityOptions {
|
|
688
|
+
/**
|
|
689
|
+
* How to handle a resolver identity that violates the contract at the trust
|
|
690
|
+
* boundary. Defaults to `"anonymous"` (a forged claim set is downgraded to
|
|
691
|
+
* anonymous rather than flowing in as an unchecked cast).
|
|
692
|
+
*/
|
|
693
|
+
readonly onInvalid?: IdentityRejectMode;
|
|
694
|
+
}
|
|
695
|
+
/** Result of validating a candidate identity against the contract. */
|
|
696
|
+
type IdentityValidation = {
|
|
697
|
+
ok: true;
|
|
698
|
+
} | {
|
|
699
|
+
error: string;
|
|
700
|
+
ok: false;
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* A declared identity claim contract. Carries the codegen discovery brand, the
|
|
704
|
+
* declared claim validators, the reject policy, and a runtime `validate`. The
|
|
705
|
+
* `TClaims` type parameter is the inferred claim shape (always extending
|
|
706
|
+
* `{ userId: string }`); it is phantom (no runtime field) and exists so
|
|
707
|
+
* `@lunora/codegen` and {@link InferIdentity} can recover the type.
|
|
708
|
+
*/
|
|
709
|
+
interface IdentityContract<TClaims extends {
|
|
710
|
+
userId: string;
|
|
711
|
+
} = {
|
|
712
|
+
userId: string;
|
|
713
|
+
}> {
|
|
714
|
+
/**
|
|
715
|
+
* Phantom carrier for the inferred claim type. Never populated at runtime
|
|
716
|
+
* (`undefined`); present only so the type flows to codegen / {@link InferIdentity}.
|
|
717
|
+
*/
|
|
718
|
+
readonly __claimType?: TClaims;
|
|
719
|
+
readonly __lunoraIdentity: true;
|
|
720
|
+
/** The declared claim validators (a `@lunora/values` validator map). */
|
|
721
|
+
readonly claims: ValidatorMap;
|
|
722
|
+
/** Reject policy applied at the trust boundary. See {@link IdentityRejectMode}. */
|
|
723
|
+
readonly onInvalid: IdentityRejectMode;
|
|
724
|
+
/**
|
|
725
|
+
* Validate a resolver's returned identity against the declared claims. On
|
|
726
|
+
* success the caller keeps the original identity untouched (so undeclared
|
|
727
|
+
* claims are forwarded verbatim, preserving today's behaviour); on failure
|
|
728
|
+
* the worker applies the `onInvalid` policy.
|
|
729
|
+
*/
|
|
730
|
+
validate: (identity: Record<string, unknown>) => IdentityValidation;
|
|
731
|
+
}
|
|
732
|
+
/** Recover the declared claim type from a {@link defineIdentity} contract. */
|
|
733
|
+
type InferIdentity<T> = T extends IdentityContract<infer TClaims> ? TClaims : never;
|
|
734
|
+
/**
|
|
735
|
+
* Declare the identity claim contract. `claims` is a `@lunora/values` validator
|
|
736
|
+
* map whose inferred type must extend `{ userId: string }` — if it does not
|
|
737
|
+
* (e.g. `userId` is missing or not a required string), the argument type
|
|
738
|
+
* collapses to `never` and the call fails to typecheck.
|
|
739
|
+
* @example
|
|
740
|
+
* export const identity = defineIdentity({ userId: v.string(), tenantId: v.optional(v.string()), scopes: v.optional(v.array(v.string())) });
|
|
741
|
+
*/
|
|
742
|
+
declare const defineIdentity: <A extends ValidatorMap>(claims: InferValidatorMap<A> extends {
|
|
743
|
+
userId: string;
|
|
744
|
+
} ? A : never, options?: DefineIdentityOptions) => IdentityContract<InferValidatorMap<A> & {
|
|
745
|
+
userId: string;
|
|
746
|
+
}>;
|
|
677
747
|
/** Handler for a connection-lifecycle hook. */
|
|
678
748
|
type LifecycleHandler = (context: MutationCtx, event: LifecycleEvent) => Promise<void> | void;
|
|
679
749
|
/** Register a hook that fires once when a client's WebSocket connects. */
|
|
@@ -1576,7 +1646,7 @@ declare const definePolicy: <Context = unknown>(input: DefinePolicyInput<Context
|
|
|
1576
1646
|
* the compile-time surface narrows, so a policy authored either way is
|
|
1577
1647
|
* discovered identically by the `rls()` chain.
|
|
1578
1648
|
*/
|
|
1579
|
-
declare const createPolicyDsl: <DM, REL extends Record<keyof DM, object>>() => <T extends keyof DM, Context = unknown>(input: TypedDefinePolicyInput<DM, REL, T, Context>) => Policy<Context>;
|
|
1649
|
+
declare const createPolicyDsl: <DM, REL extends Record<keyof DM, object>, Identity = Record<string, unknown>>() => <T extends keyof DM, Context = unknown>(input: TypedDefinePolicyInput<DM, REL, T, Context, Identity>) => Policy<Context>;
|
|
1580
1650
|
/**
|
|
1581
1651
|
* Declare a named permission a policy can check with `ctx.auth.can(...)`. Grant
|
|
1582
1652
|
* it to a role through `defineRole`'s `permissions`, register those roles with
|
|
@@ -1982,4 +2052,4 @@ interface StorageContextIn {
|
|
|
1982
2052
|
}
|
|
1983
2053
|
declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
|
|
1984
2054
|
declare const VERSION = "0.0.0";
|
|
1985
|
-
export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, type DataModelInit, type DefineComponentOptions, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExtendableSchema, type FacadeEntry, type FacadeWriterLike, type FunctionKind, type HttpActionCtx, type HttpActionHandler, type HttpMethod, type HttpRoute, type HttpRouteBuilder, type HttpRouteFactory, type HttpRouteHandlerOptions, type HttpStreamHandlerOptions, type InferArgs, type InferEnv, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraErrorCode, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationDefinition, type MigrationDocument, type MigrationTransform, type MutationBuilder, type MutationCtx, type MutatorDefinition, type OnDeleteAction, type OneRelation, type OrmLike, DEFAULT_TTL_MS as PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, type Permission, type Plugin, type Policy, type PrefixedTables, type PresenceComponent, type PresenceFunctions, type PresenceMember, type ProtectPublicOptions, type QueryBuilder, type QueryCtx, type RankIndexDefinition, type RankIndexOptions, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type StorageOperation, type StorageRule, type StorageRuleContext, type StorageRuleDecision, type StorageRulesOptions, type TableBuilder, type TableDefinition, type TerminalKind, type TriggerBuilder, type TriggerDefinition, type TypedDefinePolicyInput, VERSION, type VectorEmbedder, type VectorIndexDefinition, type VectorIndexOptions, type VectorMetric, type VectorizeOptions, type WhereInput, asBucketStorage, bindOrm, bindTableFacade, buildRlsReadRegistry, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineAggregateIndex, defineComponent, defineEnv, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, httpAction, httpRoute, httpRouter, initLunora, installPlugins, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules };
|
|
2055
|
+
export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, type DataModelInit, type DefineComponentOptions, type DefineIdentityOptions, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExtendableSchema, type FacadeEntry, type FacadeWriterLike, type FunctionKind, type HttpActionCtx, type HttpActionHandler, type HttpMethod, type HttpRoute, type HttpRouteBuilder, type HttpRouteFactory, type HttpRouteHandlerOptions, type HttpStreamHandlerOptions, type IdentityContract, type IdentityRejectMode, type IdentityValidation, type InferArgs, type InferEnv, type InferIdentity, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraErrorCode, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationDefinition, type MigrationDocument, type MigrationTransform, type MutationBuilder, type MutationCtx, type MutatorDefinition, type OnDeleteAction, type OneRelation, type OrmLike, DEFAULT_TTL_MS as PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, type Permission, type Plugin, type Policy, type PrefixedTables, type PresenceComponent, type PresenceFunctions, type PresenceMember, type ProtectPublicOptions, type QueryBuilder, type QueryCtx, type RankIndexDefinition, type RankIndexOptions, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type StorageOperation, type StorageRule, type StorageRuleContext, type StorageRuleDecision, type StorageRulesOptions, type TableBuilder, type TableDefinition, type TerminalKind, type TriggerBuilder, type TriggerDefinition, type TypedDefinePolicyInput, VERSION, type VectorEmbedder, type VectorIndexDefinition, type VectorIndexOptions, type VectorMetric, type VectorizeOptions, type WhereInput, asBucketStorage, bindOrm, bindTableFacade, buildRlsReadRegistry, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineAggregateIndex, defineComponent, defineEnv, defineIdentity, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, httpAction, httpRoute, httpRouter, initLunora, installPlugins, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ export { type ColumnValidator, type Id, type Infer, ValidationError, type Valida
|
|
|
3
3
|
import { ArgsValidator, InferArgs, RegisteredAction, ActionCtx, MutationCtx, RegisteredMutation, QueryCtx, RegisteredQuery, RegisteredStream, FunctionKind, Secrets, LifecycleEvent, RegisteredLifecycleHook, TableDefinition, RegisteredFunction, VectorIndexDefinition, Schema, AggregateOp, DurableObjectJurisdiction, RelationDefinition, GlobalBackend, OnDeleteAction, ExternalSourceDefinition, TriggerBuilder, TriggerDefinition, VectorEmbedder, VectorMetric, AggregateIndexDefinition, RankIndexDefinition } from "./types.js";
|
|
4
4
|
export { type AnyApi, type AuthState, type DatabaseReader, type DatabaseWriter, type FunctionVisibility, type IndexDefinition, type IndexRangeBuilder, type LifecycleEventKind, type LunoraLogger, type PaginationOptions, type PaginationResult, type RankSortKey, type ReadOnlyStorage, type ScheduledFunctionDoc, type ScheduledJob, type Scheduler, type SearchFilterBuilder, type SearchIndexDefinition, type ShardMode, type Storage, type StorageMetadata, type SystemDatabaseReader, type SystemDoc, type SystemQuery, type SystemTableName, type TableReader, type TableVectorIndex, type TriggerAggregateOptions, type TriggerCtx, type TriggerDatabase, type TriggerDeleteEvent, type TriggerEvent, type TriggerGroupByEntry, type TriggerGroupByOptions, type TriggerHandler, type TriggerInsertEvent, type TriggerOp, type TriggerQueryArgs, type TriggerQueryPage, type TriggerRankOptions, type TriggerRankPageOptions, type TriggerRankResult, type TriggerRow, type TriggerTiming, type TriggerUpdateEvent, type VectorMatch, type VectorMatches, type VectorQueryInput, type VectorRecord, type VectorSearch, type VectorSearchReader, type VectorUpsertInput, type WorkflowCreateOptions, type WorkflowHandle, type WorkflowInstance, type WorkflowInstanceStatus, type WorkflowStatusResult, type Workflows, anyApi } from "./types.js";
|
|
5
5
|
import { Context, Hono } from 'hono';
|
|
6
|
-
import { b as Permission, R as Role, T as TypedDefinePolicyInput, a as Policy, D as DefinePolicyInput, W as WhereInput, c as RlsOptions } from "./packem_shared/types.d-
|
|
7
|
-
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-
|
|
6
|
+
import { b as Permission, R as Role, T as TypedDefinePolicyInput, a as Policy, D as DefinePolicyInput, W as WhereInput, c as RlsOptions } from "./packem_shared/types.d-Cxl6ndhm.js";
|
|
7
|
+
export type { d as PolicyContext, e as PolicyDecision, f as PolicyDecisionOf, P as PolicyOperation } from "./packem_shared/types.d-Cxl6ndhm.js";
|
|
8
8
|
export { type CronJob, type CronJobsBuilder, type CronScheduleKind, type DailySchedule, type IntervalSchedule, type MonthlySchedule, type WeeklySchedule, cronJobs } from '@lunora/scheduler';
|
|
9
9
|
import "./data-model.js";
|
|
10
10
|
/**
|
|
@@ -674,6 +674,76 @@ interface ContextWithStorage {
|
|
|
674
674
|
* client then ranges against R2/CDN directly with no Worker hop.
|
|
675
675
|
*/
|
|
676
676
|
declare const serveStorageObject: (context: ContextWithStorage, key: string, request: Request) => Promise<Response>;
|
|
677
|
+
/**
|
|
678
|
+
* What the worker does with a resolver's identity when it fails contract
|
|
679
|
+
* validation (a forged / malformed claim set arriving from an untrusted token).
|
|
680
|
+
* `"anonymous"` (default, safe) treats the request as anonymous, so the bad
|
|
681
|
+
* identity never reaches a policy as a valid identity (`ctx.auth.userId`
|
|
682
|
+
* becomes `undefined`). `"reject"` fails the request closed (a `401`) — use
|
|
683
|
+
* when a malformed credential should be a hard error, not a silent downgrade.
|
|
684
|
+
*/
|
|
685
|
+
type IdentityRejectMode = "anonymous" | "reject";
|
|
686
|
+
/** Options for {@link defineIdentity}. */
|
|
687
|
+
interface DefineIdentityOptions {
|
|
688
|
+
/**
|
|
689
|
+
* How to handle a resolver identity that violates the contract at the trust
|
|
690
|
+
* boundary. Defaults to `"anonymous"` (a forged claim set is downgraded to
|
|
691
|
+
* anonymous rather than flowing in as an unchecked cast).
|
|
692
|
+
*/
|
|
693
|
+
readonly onInvalid?: IdentityRejectMode;
|
|
694
|
+
}
|
|
695
|
+
/** Result of validating a candidate identity against the contract. */
|
|
696
|
+
type IdentityValidation = {
|
|
697
|
+
ok: true;
|
|
698
|
+
} | {
|
|
699
|
+
error: string;
|
|
700
|
+
ok: false;
|
|
701
|
+
};
|
|
702
|
+
/**
|
|
703
|
+
* A declared identity claim contract. Carries the codegen discovery brand, the
|
|
704
|
+
* declared claim validators, the reject policy, and a runtime `validate`. The
|
|
705
|
+
* `TClaims` type parameter is the inferred claim shape (always extending
|
|
706
|
+
* `{ userId: string }`); it is phantom (no runtime field) and exists so
|
|
707
|
+
* `@lunora/codegen` and {@link InferIdentity} can recover the type.
|
|
708
|
+
*/
|
|
709
|
+
interface IdentityContract<TClaims extends {
|
|
710
|
+
userId: string;
|
|
711
|
+
} = {
|
|
712
|
+
userId: string;
|
|
713
|
+
}> {
|
|
714
|
+
/**
|
|
715
|
+
* Phantom carrier for the inferred claim type. Never populated at runtime
|
|
716
|
+
* (`undefined`); present only so the type flows to codegen / {@link InferIdentity}.
|
|
717
|
+
*/
|
|
718
|
+
readonly __claimType?: TClaims;
|
|
719
|
+
readonly __lunoraIdentity: true;
|
|
720
|
+
/** The declared claim validators (a `@lunora/values` validator map). */
|
|
721
|
+
readonly claims: ValidatorMap;
|
|
722
|
+
/** Reject policy applied at the trust boundary. See {@link IdentityRejectMode}. */
|
|
723
|
+
readonly onInvalid: IdentityRejectMode;
|
|
724
|
+
/**
|
|
725
|
+
* Validate a resolver's returned identity against the declared claims. On
|
|
726
|
+
* success the caller keeps the original identity untouched (so undeclared
|
|
727
|
+
* claims are forwarded verbatim, preserving today's behaviour); on failure
|
|
728
|
+
* the worker applies the `onInvalid` policy.
|
|
729
|
+
*/
|
|
730
|
+
validate: (identity: Record<string, unknown>) => IdentityValidation;
|
|
731
|
+
}
|
|
732
|
+
/** Recover the declared claim type from a {@link defineIdentity} contract. */
|
|
733
|
+
type InferIdentity<T> = T extends IdentityContract<infer TClaims> ? TClaims : never;
|
|
734
|
+
/**
|
|
735
|
+
* Declare the identity claim contract. `claims` is a `@lunora/values` validator
|
|
736
|
+
* map whose inferred type must extend `{ userId: string }` — if it does not
|
|
737
|
+
* (e.g. `userId` is missing or not a required string), the argument type
|
|
738
|
+
* collapses to `never` and the call fails to typecheck.
|
|
739
|
+
* @example
|
|
740
|
+
* export const identity = defineIdentity({ userId: v.string(), tenantId: v.optional(v.string()), scopes: v.optional(v.array(v.string())) });
|
|
741
|
+
*/
|
|
742
|
+
declare const defineIdentity: <A extends ValidatorMap>(claims: InferValidatorMap<A> extends {
|
|
743
|
+
userId: string;
|
|
744
|
+
} ? A : never, options?: DefineIdentityOptions) => IdentityContract<InferValidatorMap<A> & {
|
|
745
|
+
userId: string;
|
|
746
|
+
}>;
|
|
677
747
|
/** Handler for a connection-lifecycle hook. */
|
|
678
748
|
type LifecycleHandler = (context: MutationCtx, event: LifecycleEvent) => Promise<void> | void;
|
|
679
749
|
/** Register a hook that fires once when a client's WebSocket connects. */
|
|
@@ -1576,7 +1646,7 @@ declare const definePolicy: <Context = unknown>(input: DefinePolicyInput<Context
|
|
|
1576
1646
|
* the compile-time surface narrows, so a policy authored either way is
|
|
1577
1647
|
* discovered identically by the `rls()` chain.
|
|
1578
1648
|
*/
|
|
1579
|
-
declare const createPolicyDsl: <DM, REL extends Record<keyof DM, object>>() => <T extends keyof DM, Context = unknown>(input: TypedDefinePolicyInput<DM, REL, T, Context>) => Policy<Context>;
|
|
1649
|
+
declare const createPolicyDsl: <DM, REL extends Record<keyof DM, object>, Identity = Record<string, unknown>>() => <T extends keyof DM, Context = unknown>(input: TypedDefinePolicyInput<DM, REL, T, Context, Identity>) => Policy<Context>;
|
|
1580
1650
|
/**
|
|
1581
1651
|
* Declare a named permission a policy can check with `ctx.auth.can(...)`. Grant
|
|
1582
1652
|
* it to a role through `defineRole`'s `permissions`, register those roles with
|
|
@@ -1982,4 +2052,4 @@ interface StorageContextIn {
|
|
|
1982
2052
|
}
|
|
1983
2053
|
declare const storageRules: <Context extends StorageContextIn = StorageContextIn>(rules: ReadonlyArray<StorageRule<Context>>, options?: StorageRulesOptions) => Middleware<Context, Context>;
|
|
1984
2054
|
declare const VERSION = "0.0.0";
|
|
1985
|
-
export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, type DataModelInit, type DefineComponentOptions, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExtendableSchema, type FacadeEntry, type FacadeWriterLike, type FunctionKind, type HttpActionCtx, type HttpActionHandler, type HttpMethod, type HttpRoute, type HttpRouteBuilder, type HttpRouteFactory, type HttpRouteHandlerOptions, type HttpStreamHandlerOptions, type InferArgs, type InferEnv, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraErrorCode, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationDefinition, type MigrationDocument, type MigrationTransform, type MutationBuilder, type MutationCtx, type MutatorDefinition, type OnDeleteAction, type OneRelation, type OrmLike, DEFAULT_TTL_MS as PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, type Permission, type Plugin, type Policy, type PrefixedTables, type PresenceComponent, type PresenceFunctions, type PresenceMember, type ProtectPublicOptions, type QueryBuilder, type QueryCtx, type RankIndexDefinition, type RankIndexOptions, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type StorageOperation, type StorageRule, type StorageRuleContext, type StorageRuleDecision, type StorageRulesOptions, type TableBuilder, type TableDefinition, type TerminalKind, type TriggerBuilder, type TriggerDefinition, type TypedDefinePolicyInput, VERSION, type VectorEmbedder, type VectorIndexDefinition, type VectorIndexOptions, type VectorMetric, type VectorizeOptions, type WhereInput, asBucketStorage, bindOrm, bindTableFacade, buildRlsReadRegistry, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineAggregateIndex, defineComponent, defineEnv, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, httpAction, httpRoute, httpRouter, initLunora, installPlugins, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules };
|
|
2055
|
+
export { type ActionBuilder, type ActionCtx, type AggregateIndexDefinition, type AggregateIndexOptions, type AggregateOp, type ArgsValidator, type Component, type ComponentFunctions, type CreateOptions, type DataModelInit, type DefineComponentOptions, type DefineIdentityOptions, type DefinePluginOptions, type DefinePolicyInput, type DefinePresenceOptions, type DefineStorageRuleInput, type DurableObjectJurisdiction, type EmptyArgs, type EnvAccessor, type EnvKeyFailure, type EnvShape, type ExtendableSchema, type FacadeEntry, type FacadeWriterLike, type FunctionKind, type HttpActionCtx, type HttpActionHandler, type HttpMethod, type HttpRoute, type HttpRouteBuilder, type HttpRouteFactory, type HttpRouteHandlerOptions, type HttpStreamHandlerOptions, type IdentityContract, type IdentityRejectMode, type IdentityValidation, type InferArgs, type InferEnv, type InferIdentity, type InlineAggregateIndexOptions, type InlineRankIndexOptions, type InternalActionBuilder, type InternalMutationBuilder, type InternalQueryBuilder, type LifecycleEvent, type LifecycleHandler, type LunoraBuilders, LunoraEnvError, LunoraError, type LunoraErrorCode, type LunoraHttpApp, type LunoraHttpEnv, type LunoraRouteHandler, type ManyRelation, type MaskColumns, type MaskContext, type MaskFn, type MaskOptions, type MaskPolicies, type MaskStrategy, type Middleware, type MiddlewareNext, type MigrationDefinition, type MigrationDocument, type MigrationTransform, type MutationBuilder, type MutationCtx, type MutatorDefinition, type OnDeleteAction, type OneRelation, type OrmLike, DEFAULT_TTL_MS as PRESENCE_DEFAULT_TTL_MS, PRESENCE_TABLE, type Permission, type Plugin, type Policy, type PrefixedTables, type PresenceComponent, type PresenceFunctions, type PresenceMember, type ProtectPublicOptions, type QueryBuilder, type QueryCtx, type RankIndexDefinition, type RankIndexOptions, type RegisteredAction, type RegisteredFunction, type RegisteredLifecycleHook, type RegisteredMigration, type RegisteredMutation, type RegisteredMutator, type RegisteredQuery, type RegisteredShape, type RegisteredStream, type RelationBuilder, type RelationDefinition, type RlsOptions, type RlsReadRegistry, type Role, type Schema, type SchemaExtension, type ShapeDefinition, type ShapeReadWhereRequest, type StorageOperation, type StorageRule, type StorageRuleContext, type StorageRuleDecision, type StorageRulesOptions, type TableBuilder, type TableDefinition, type TerminalKind, type TriggerBuilder, type TriggerDefinition, type TypedDefinePolicyInput, VERSION, type VectorEmbedder, type VectorIndexDefinition, type VectorIndexOptions, type VectorMetric, type VectorizeOptions, type WhereInput, asBucketStorage, bindOrm, bindTableFacade, buildRlsReadRegistry, composePluginMiddleware, composeShapeReadWhere, createPolicyDsl, createSecrets, defineAggregateIndex, defineComponent, defineEnv, defineIdentity, defineMigration, defineMutator, definePermission, definePlugin, definePolicies, definePolicy, definePresence, defineRankIndex, defineRole, defineSchema, defineSchemaExtension, defineShape, defineStorageRule, defineStorageRules, defineTable, defineVectorIndex, httpAction, httpRoute, httpRouter, initLunora, installPlugins, mask, mergeSchemaExtension, onConnect, onDisconnect, presenceExtension, protectPublic, redactSecrets, rls, serveStorageObject, storageRules };
|
package/dist/index.mjs
CHANGED
|
@@ -5,6 +5,7 @@ export { LunoraEnvError, defineEnv, redactSecrets } from './packem_shared/Lunora
|
|
|
5
5
|
export { LunoraError } from './packem_shared/LunoraError-DN7Zhhvu.mjs';
|
|
6
6
|
export { bindOrm, bindTableFacade } from './packem_shared/bindOrm-Ce57S3N9.mjs';
|
|
7
7
|
export { httpAction, httpRoute, httpRouter, serveStorageObject } from './packem_shared/httpAction-FLwfsePg.mjs';
|
|
8
|
+
export { defineIdentity } from './packem_shared/defineIdentity-B_9YD46A.mjs';
|
|
8
9
|
export { onConnect, onDisconnect } from './packem_shared/onConnect-CIPXKPyw.mjs';
|
|
9
10
|
export { defineMigration } from './packem_shared/defineMigration-CAJLr6fx.mjs';
|
|
10
11
|
export { defineMutator } from './packem_shared/defineMutator-EIXAWhs9.mjs';
|
|
@@ -16,11 +17,11 @@ export { defineShape } from './packem_shared/defineShape-CJ27Wx7o.mjs';
|
|
|
16
17
|
export { anyApi } from './types.mjs';
|
|
17
18
|
export { cronJobs } from '@lunora/scheduler';
|
|
18
19
|
export { ValidationError, v } from '@lunora/values';
|
|
19
|
-
export { buildRlsReadRegistry, composeShapeReadWhere } from './packem_shared/buildRlsReadRegistry-
|
|
20
|
+
export { buildRlsReadRegistry, composeShapeReadWhere } from './packem_shared/buildRlsReadRegistry-Do1CSBTr.mjs';
|
|
20
21
|
export { createPolicyDsl, definePermission, definePolicies, definePolicy, defineRole } from './packem_shared/createPolicyDsl-De67zPDS.mjs';
|
|
21
22
|
export { defineStorageRule, defineStorageRules } from './packem_shared/defineStorageRule-qu0mpilX.mjs';
|
|
22
|
-
export { mask } from './packem_shared/mask-
|
|
23
|
-
export { rls } from './packem_shared/rls-
|
|
23
|
+
export { mask } from './packem_shared/mask-CWfMjb5Y.mjs';
|
|
24
|
+
export { rls } from './packem_shared/rls-DhNgKFeW.mjs';
|
|
24
25
|
export { storageRules } from './packem_shared/storageRules-Cje6Woea.mjs';
|
|
25
26
|
|
|
26
27
|
const VERSION = "0.0.0";
|
package/dist/packem_shared/{buildRlsReadRegistry-1jexWrb3.mjs → buildRlsReadRegistry-Do1CSBTr.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { indexRolePermissions, computeReadBaseWhere, permissionName } from './rls-
|
|
1
|
+
import { indexRolePermissions, computeReadBaseWhere, permissionName } from './rls-DhNgKFeW.mjs';
|
|
2
2
|
import { r as readRlsTag } from './policy-tag-DvpVH2tv.mjs';
|
|
3
3
|
|
|
4
4
|
const FALSE_PREDICATE = { OR: [] };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseValidatorMap, ValidationError } from '@lunora/values';
|
|
2
|
+
|
|
3
|
+
const NON_STRING_USER_ID_KINDS = /* @__PURE__ */ new Set([
|
|
4
|
+
"array",
|
|
5
|
+
"bigint",
|
|
6
|
+
"boolean",
|
|
7
|
+
"bytes",
|
|
8
|
+
"date",
|
|
9
|
+
"null",
|
|
10
|
+
"number",
|
|
11
|
+
"object",
|
|
12
|
+
"optional",
|
|
13
|
+
"record",
|
|
14
|
+
"timestamp"
|
|
15
|
+
]);
|
|
16
|
+
const defineIdentity = (claims, options = {}) => {
|
|
17
|
+
const map = claims;
|
|
18
|
+
const userIdValidator = map["userId"];
|
|
19
|
+
if (userIdValidator === void 0 || NON_STRING_USER_ID_KINDS.has(userIdValidator.kind)) {
|
|
20
|
+
throw new Error("defineIdentity: the claim map must declare a required string `userId` validator (e.g. `v.string()` or `v.id(...)`)");
|
|
21
|
+
}
|
|
22
|
+
const onInvalid = options.onInvalid ?? "anonymous";
|
|
23
|
+
const validate = (identity) => {
|
|
24
|
+
try {
|
|
25
|
+
parseValidatorMap(map, identity, "identity");
|
|
26
|
+
return { ok: true };
|
|
27
|
+
} catch (error) {
|
|
28
|
+
return { error: error instanceof ValidationError ? error.message : String(error), ok: false };
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
return { __lunoraIdentity: true, claims: map, onInvalid, validate };
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export { defineIdentity };
|
|
@@ -60,8 +60,13 @@ const wrapDatabase = (base, perTable, context) => {
|
|
|
60
60
|
const rows = await reader.collect();
|
|
61
61
|
return rows.map((row) => maskRow(row, columns, context));
|
|
62
62
|
},
|
|
63
|
+
// SECURITY (value oracle): the predicate must see the MASKED row, not
|
|
64
|
+
// the raw stored row — otherwise a caller can `.filter(d => d.ssn ===
|
|
65
|
+
// guess)` to read the value the mask hides. Masking before the
|
|
66
|
+
// predicate keeps filtering on non-masked columns working while
|
|
67
|
+
// redacting masked cells the predicate can observe.
|
|
63
68
|
filter: (predicate) => wrapReader(
|
|
64
|
-
reader.filter((document) => predicate(document)),
|
|
69
|
+
reader.filter((document) => predicate(maskRow(document, columns, context))),
|
|
65
70
|
columns
|
|
66
71
|
),
|
|
67
72
|
first: async () => {
|
|
@@ -120,23 +125,63 @@ const wrapDatabase = (base, perTable, context) => {
|
|
|
120
125
|
throw new LunoraError("MASK_UNSUPPORTED", `${method}() over masked column "${offending}" on "${tableName}" is not supported`);
|
|
121
126
|
}
|
|
122
127
|
};
|
|
128
|
+
const collectWhereFields = (where, into) => {
|
|
129
|
+
if (!where || typeof where !== "object" || Array.isArray(where)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
for (const [key, value] of Object.entries(where)) {
|
|
133
|
+
if (key === "AND" || key === "OR") {
|
|
134
|
+
if (Array.isArray(value)) {
|
|
135
|
+
for (const clause of value) {
|
|
136
|
+
collectWhereFields(clause, into);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
} else if (key === "NOT") {
|
|
140
|
+
collectWhereFields(value, into);
|
|
141
|
+
} else if (!key.startsWith("__")) {
|
|
142
|
+
into.add(key);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const assertWhereAllowed = (tableName, where, method) => {
|
|
147
|
+
const columns = perTable.get(tableName);
|
|
148
|
+
if (!columns || where === void 0) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const referenced = /* @__PURE__ */ new Set();
|
|
152
|
+
collectWhereFields(where, referenced);
|
|
153
|
+
for (const field of referenced) {
|
|
154
|
+
if (field in columns) {
|
|
155
|
+
throw new LunoraError("MASK_UNSUPPORTED", `${method}() filtering "${tableName}" by masked column "${field}" is not supported`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
123
159
|
const wrapped = {
|
|
124
160
|
...base,
|
|
125
161
|
aggregate(tableName, options) {
|
|
126
162
|
assertReductionAllowed(tableName, [options.field], "aggregate");
|
|
127
163
|
return base.aggregate(tableName, options);
|
|
128
164
|
},
|
|
165
|
+
count(tableName, whereOrArgs) {
|
|
166
|
+
const wrapper = whereOrArgs && typeof whereOrArgs === "object" && !Array.isArray(whereOrArgs) ? whereOrArgs : void 0;
|
|
167
|
+
const where = wrapper && ("where" in wrapper || "baseWhere" in wrapper || "restrictsCounts" in wrapper) ? wrapper.where : whereOrArgs;
|
|
168
|
+
assertWhereAllowed(tableName, where, "count");
|
|
169
|
+
return base.count(tableName, whereOrArgs);
|
|
170
|
+
},
|
|
129
171
|
async findFirst(tableName, args) {
|
|
172
|
+
assertWhereAllowed(tableName, args?.where, "findFirst");
|
|
130
173
|
const row = await base.findFirst(tableName, args);
|
|
131
174
|
const columns = perTable.get(tableName);
|
|
132
175
|
return row && columns ? maskRow(row, columns, context) : row;
|
|
133
176
|
},
|
|
134
177
|
async findFirstOrThrow(tableName, args) {
|
|
178
|
+
assertWhereAllowed(tableName, args?.where, "findFirstOrThrow");
|
|
135
179
|
const row = await base.findFirstOrThrow(tableName, args);
|
|
136
180
|
const columns = perTable.get(tableName);
|
|
137
181
|
return columns ? maskRow(row, columns, context) : row;
|
|
138
182
|
},
|
|
139
183
|
async findMany(tableName, args) {
|
|
184
|
+
assertWhereAllowed(tableName, args?.where, "findMany");
|
|
140
185
|
const page = await base.findMany(tableName, args);
|
|
141
186
|
const columns = perTable.get(tableName);
|
|
142
187
|
return columns ? maskPage(page, columns, context) : page;
|
|
@@ -245,7 +245,6 @@ const isFacadeEntry = (value) => {
|
|
|
245
245
|
return typeof candidate["findMany"] === "function" && typeof candidate["withSearchIndex"] === "function";
|
|
246
246
|
};
|
|
247
247
|
const wrapDatabase = (base, raw, perTable, context) => {
|
|
248
|
-
const route = (tableName) => perTable.has(tableName) ? raw : base;
|
|
249
248
|
const readBaseCache = /* @__PURE__ */ new Map();
|
|
250
249
|
const readBase = (tableName) => {
|
|
251
250
|
const cached = readBaseCache.get(tableName);
|
|
@@ -263,6 +262,7 @@ const wrapDatabase = (base, raw, perTable, context) => {
|
|
|
263
262
|
readBaseCache.set(tableName, result);
|
|
264
263
|
return result;
|
|
265
264
|
};
|
|
265
|
+
const route = (tableName) => readBase(tableName).restricts ? raw : base;
|
|
266
266
|
const relationReadFilter = (table) => readBase(table).baseWhere;
|
|
267
267
|
const locateRow = async (id, expectedTable) => {
|
|
268
268
|
if (raw.lookupById) {
|
|
@@ -300,7 +300,7 @@ const wrapDatabase = (base, raw, perTable, context) => {
|
|
|
300
300
|
const nextRow = computeNextRow ? computeNextRow(located.row) : void 0;
|
|
301
301
|
const writeOk = evaluateWrite(policies, op, { ...context, row: located.row }, nextRow);
|
|
302
302
|
if (!writeOk) {
|
|
303
|
-
throw new LunoraError("FORBIDDEN", `${op}
|
|
303
|
+
throw new LunoraError("FORBIDDEN", `${op} denied by policy`);
|
|
304
304
|
}
|
|
305
305
|
}
|
|
306
306
|
return perform(raw);
|
|
@@ -366,7 +366,10 @@ const wrapDatabase = (base, raw, perTable, context) => {
|
|
|
366
366
|
return base.get(id, expectedTable);
|
|
367
367
|
}
|
|
368
368
|
const { baseWhere, restricts } = readBase(located.tableName);
|
|
369
|
-
if (!restricts
|
|
369
|
+
if (!restricts) {
|
|
370
|
+
return base.get(id, expectedTable);
|
|
371
|
+
}
|
|
372
|
+
if (!baseWhere) {
|
|
370
373
|
return located.row;
|
|
371
374
|
}
|
|
372
375
|
const allowed = await raw.findFirst(located.tableName, { baseWhere, limit: 1, where: { _id: id } });
|
|
@@ -45,10 +45,10 @@ type PolicyDecisionOf<DM, REL extends Record<keyof DM, object>, T extends keyof
|
|
|
45
45
|
* unknown table, a stray column, or a relation predicate naming a relation the
|
|
46
46
|
* table does not declare is a compile error rather than a silent runtime deny.
|
|
47
47
|
*/
|
|
48
|
-
interface TypedDefinePolicyInput<DM, REL extends Record<keyof DM, object>, T extends keyof DM, Context = unknown
|
|
48
|
+
interface TypedDefinePolicyInput<DM, REL extends Record<keyof DM, object>, T extends keyof DM, Context = unknown, Identity = Record<string, unknown>> {
|
|
49
49
|
on: PolicyOperation;
|
|
50
50
|
table: T;
|
|
51
|
-
when: (context: PolicyContext<Context>) => PolicyDecisionOf<DM, REL, T>;
|
|
51
|
+
when: (context: PolicyContext<Context, Identity>) => PolicyDecisionOf<DM, REL, T>;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Context handed to a policy. `auth.roles` is the per-request role list,
|
|
@@ -59,7 +59,7 @@ interface TypedDefinePolicyInput<DM, REL extends Record<keyof DM, object>, T ext
|
|
|
59
59
|
* pre-write row; for `insert` it is the candidate document. `ctx` is the full
|
|
60
60
|
* procedure context the middleware closed over.
|
|
61
61
|
*/
|
|
62
|
-
interface PolicyContext<Context = unknown
|
|
62
|
+
interface PolicyContext<Context = unknown, Identity = Record<string, unknown>> {
|
|
63
63
|
readonly auth: {
|
|
64
64
|
/**
|
|
65
65
|
* `true` when any of the request's `roles` grants `permission` (passed
|
|
@@ -68,7 +68,13 @@ interface PolicyContext<Context = unknown> {
|
|
|
68
68
|
* when none of the request's roles lists the permission.
|
|
69
69
|
*/
|
|
70
70
|
readonly can: (permission: Permission | string) => boolean;
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The resolved identity, typed to the `Identity` type parameter bound on
|
|
73
|
+
* `createPolicyDsl` — e.g. the app's `defineIdentity(...)` claim type via
|
|
74
|
+
* the `InferIdentity` helper; otherwise the untyped claim bag.
|
|
75
|
+
* `undefined`/`null` when the request is anonymous.
|
|
76
|
+
*/
|
|
77
|
+
readonly identity?: Identity | null;
|
|
72
78
|
readonly roles: ReadonlyArray<string>;
|
|
73
79
|
readonly userId: null | string;
|
|
74
80
|
};
|
|
@@ -45,10 +45,10 @@ type PolicyDecisionOf<DM, REL extends Record<keyof DM, object>, T extends keyof
|
|
|
45
45
|
* unknown table, a stray column, or a relation predicate naming a relation the
|
|
46
46
|
* table does not declare is a compile error rather than a silent runtime deny.
|
|
47
47
|
*/
|
|
48
|
-
interface TypedDefinePolicyInput<DM, REL extends Record<keyof DM, object>, T extends keyof DM, Context = unknown
|
|
48
|
+
interface TypedDefinePolicyInput<DM, REL extends Record<keyof DM, object>, T extends keyof DM, Context = unknown, Identity = Record<string, unknown>> {
|
|
49
49
|
on: PolicyOperation;
|
|
50
50
|
table: T;
|
|
51
|
-
when: (context: PolicyContext<Context>) => PolicyDecisionOf<DM, REL, T>;
|
|
51
|
+
when: (context: PolicyContext<Context, Identity>) => PolicyDecisionOf<DM, REL, T>;
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Context handed to a policy. `auth.roles` is the per-request role list,
|
|
@@ -59,7 +59,7 @@ interface TypedDefinePolicyInput<DM, REL extends Record<keyof DM, object>, T ext
|
|
|
59
59
|
* pre-write row; for `insert` it is the candidate document. `ctx` is the full
|
|
60
60
|
* procedure context the middleware closed over.
|
|
61
61
|
*/
|
|
62
|
-
interface PolicyContext<Context = unknown
|
|
62
|
+
interface PolicyContext<Context = unknown, Identity = Record<string, unknown>> {
|
|
63
63
|
readonly auth: {
|
|
64
64
|
/**
|
|
65
65
|
* `true` when any of the request's `roles` grants `permission` (passed
|
|
@@ -68,7 +68,13 @@ interface PolicyContext<Context = unknown> {
|
|
|
68
68
|
* when none of the request's roles lists the permission.
|
|
69
69
|
*/
|
|
70
70
|
readonly can: (permission: Permission | string) => boolean;
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* The resolved identity, typed to the `Identity` type parameter bound on
|
|
73
|
+
* `createPolicyDsl` — e.g. the app's `defineIdentity(...)` claim type via
|
|
74
|
+
* the `InferIdentity` helper; otherwise the untyped claim bag.
|
|
75
|
+
* `undefined`/`null` when the request is anonymous.
|
|
76
|
+
*/
|
|
77
|
+
readonly identity?: Identity | null;
|
|
72
78
|
readonly roles: ReadonlyArray<string>;
|
|
73
79
|
readonly userId: null | string;
|
|
74
80
|
};
|
package/dist/rls/testing.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PolicyOperation, R as Role, a as Policy } from "../packem_shared/types.d-
|
|
1
|
+
import { P as PolicyOperation, R as Role, a as Policy } from "../packem_shared/types.d-BB3pjV0m.mjs";
|
|
2
2
|
import "../data-model.mjs";
|
|
3
3
|
/**
|
|
4
4
|
* The slice of a request identity a policy reads. Mirrors the
|
package/dist/rls/testing.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { P as PolicyOperation, R as Role, a as Policy } from "../packem_shared/types.d-
|
|
1
|
+
import { P as PolicyOperation, R as Role, a as Policy } from "../packem_shared/types.d-Cxl6ndhm.js";
|
|
2
2
|
import "../data-model.js";
|
|
3
3
|
/**
|
|
4
4
|
* The slice of a request identity a policy reads. Mirrors the
|
package/dist/rls/testing.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { indexRolePermissions, computeReadBaseWhere, matchesWhere, evaluateWrite, permissionName } from '../packem_shared/rls-
|
|
1
|
+
import { indexRolePermissions, computeReadBaseWhere, matchesWhere, evaluateWrite, permissionName } from '../packem_shared/rls-DhNgKFeW.mjs';
|
|
2
2
|
|
|
3
3
|
const expectPolicy = (policies, options = {}) => {
|
|
4
4
|
const rolePermissions = indexRolePermissions(options.roles);
|