@maravilla-labs/platform 0.3.3 → 0.3.7

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/config.d.ts CHANGED
@@ -42,6 +42,16 @@ type SecretRef = string | {
42
42
  env: string;
43
43
  };
44
44
 
45
+ /**
46
+ * The platform service this resource binds to. Used by the UI to offer
47
+ * service-correct action presets and policy snippets, and by the reconciler
48
+ * to validate that policies reference legal `node.*` fields for the service.
49
+ *
50
+ * Omit for legacy / cross-service umbrella resources — the runtime falls back
51
+ * to matching purely by `name` (a name collision between e.g. a KV namespace
52
+ * and a DB collection will silently share a policy, which is rarely desired).
53
+ */
54
+ type ResourceServiceType = 'kv' | 'database' | 'realtime' | 'media' | 'vector' | 'storage' | 'queue' | 'push' | 'workflow' | 'transforms';
45
55
  interface ResourceDefinition {
46
56
  /** URL-safe slug. Used as the resource key in code (e.g. the KV namespace). */
47
57
  name: string;
@@ -49,6 +59,12 @@ interface ResourceDefinition {
49
59
  title: string;
50
60
  /** Optional longer description. */
51
61
  description?: string;
62
+ /**
63
+ * Which platform service this resource gates. When set, the reconciler
64
+ * validates that the policy only references `node.*` fields legal for that
65
+ * service (e.g. a `realtime` policy can't reference `node.collection`).
66
+ */
67
+ type?: ResourceServiceType;
52
68
  /** Actions this resource supports, e.g. `['read', 'write', 'delete']`. */
53
69
  actions: string[];
54
70
  /**
@@ -57,6 +73,19 @@ interface ResourceDefinition {
57
73
  * Layer 2 for this resource — tenant + owner isolation still applies.
58
74
  */
59
75
  policy?: string;
76
+ /**
77
+ * C+D read-filter (option ii). JSON object the runtime ANDs into the
78
+ * caller's filter on `db.find` / `db.findOne`. Supports `$auth.<path>`
79
+ * placeholder strings (e.g. `"$auth.user_id"`) substituted from the
80
+ * caller's identity at request time. Allowed paths: `user_id`, `email`,
81
+ * `is_admin`, `roles`.
82
+ *
83
+ * Independent of `policy` — `policy` gates writes and resolved-doc reads;
84
+ * `read_filter` scopes which rows the caller can ever see.
85
+ *
86
+ * Example: `'{"$or":[{"owner":"$auth.user_id"},{"public":true}]}'`
87
+ */
88
+ read_filter?: string;
60
89
  }
61
90
  interface GroupPermissionDefinition {
62
91
  /** Must match a `ResourceDefinition.name`. */
@@ -244,4 +273,4 @@ interface DatabaseConfigBlock {
244
273
  */
245
274
  declare function defineConfig(config: MaravillaConfig): MaravillaConfig;
246
275
 
247
- export { type AuthConfigBlock, type BrandingConfig, type DatabaseConfigBlock, type DocumentIndexDeclaration, type GroupDefinition, type GroupPermissionDefinition, type IndexDirectionConfig, type MaravillaConfig, type OAuthProviderDefinition, type OAuthProvidersConfig, type PasswordPolicyDefinition, type RegistrationConfig, type RegistrationFieldDefinition, type RelationTypeDefinition, type ResourceDefinition, type SecretRef, type SecurityConfig, type SessionConfigDefinition, TransformsConfig, type VectorIndexDeclaration, type VectorMetricConfig, type VectorStorageConfig, defineConfig };
276
+ export { type AuthConfigBlock, type BrandingConfig, type DatabaseConfigBlock, type DocumentIndexDeclaration, type GroupDefinition, type GroupPermissionDefinition, type IndexDirectionConfig, type MaravillaConfig, type OAuthProviderDefinition, type OAuthProvidersConfig, type PasswordPolicyDefinition, type RegistrationConfig, type RegistrationFieldDefinition, type RelationTypeDefinition, type ResourceDefinition, type ResourceServiceType, type SecretRef, type SecurityConfig, type SessionConfigDefinition, TransformsConfig, type VectorIndexDeclaration, type VectorMetricConfig, type VectorStorageConfig, defineConfig };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts"],"sourcesContent":["/**\n * @fileoverview Typed schema for `maravilla.config.{ts,yaml,json}` files.\n *\n * Declares your project's auth settings (resources, groups, relations,\n * registration fields, OAuth providers, security policy, branding) alongside\n * your code. The Maravilla adapter reads this at build time and reconciles\n * the settings into delivery on deploy.\n *\n * ```typescript\n * import { defineConfig } from '@maravilla-labs/platform/config';\n *\n * export default defineConfig({\n * auth: {\n * resources: [\n * { name: 'todos', title: 'Todos', actions: ['read', 'write'],\n * policy: 'auth.user_id == node.owner' },\n * ],\n * },\n * });\n * ```\n *\n * Omitted sections leave the DB alone — partial adoption is explicitly\n * supported. List-based sections (`resources`, `groups`, `relations`,\n * `oauth`) are upserted and never auto-delete DB-only entries. Singleton\n * sections (`registration`, `security`, `branding`) are replaced wholesale\n * when declared.\n */\n\n/**\n * String value that may either be a literal secret or a reference to an\n * environment variable on the **tenant** (resolved server-side at\n * reconcile time, never shipped plaintext in the manifest).\n *\n * Accepted forms:\n * - `\"literal-value\"` — inline (not recommended for real secrets)\n * - `\"${env.VAR_NAME}\"` — string-template form\n * - `{ env: \"VAR_NAME\" }` — object form\n */\nexport type SecretRef = string | { env: string };\n\nimport type { TransformsConfig } from './transforms.js';\nexport type { TransformsConfig, TransformsPatternSpec } from './transforms.js';\n\n// ── Resources + policies ──\n\nexport interface ResourceDefinition {\n /** URL-safe slug. Used as the resource key in code (e.g. the KV namespace). */\n name: string;\n /** Human-readable title for the admin UI. */\n title: string;\n /** Optional longer description. */\n description?: string;\n /** Actions this resource supports, e.g. `['read', 'write', 'delete']`. */\n actions: string[];\n /**\n * Optional raisin-rel policy expression. Evaluated on every KV/DB/\n * realtime/media op that targets this resource. Leave empty to skip\n * Layer 2 for this resource — tenant + owner isolation still applies.\n */\n policy?: string;\n}\n\n// ── Groups ──\n\nexport interface GroupPermissionDefinition {\n /** Must match a `ResourceDefinition.name`. */\n resource_name: string;\n /** Actions this group is granted on the resource. */\n actions: string[];\n}\n\nexport interface GroupDefinition {\n /** Unique group name per tenant. */\n name: string;\n /** Optional description for the admin UI. */\n description?: string;\n /** Resource permissions granted to the group. Replaces the group's current permissions when declared. */\n permissions?: GroupPermissionDefinition[];\n}\n\n// ── Relations ──\n\nexport interface RelationTypeDefinition {\n /** Uppercase identifier used in policies (`... VIA 'STEWARDS'`). */\n relation_name: string;\n /** Human-readable title. */\n title: string;\n description?: string;\n /** Grouping for the admin UI (e.g. `\"family\"`, `\"work\"`). */\n category?: string;\n icon?: string;\n color?: string;\n /** Name of the inverse relation type, if one exists. */\n inverse_relation_name?: string;\n /** When true, membership in this relation implies stewardship rights. */\n implies_stewardship?: boolean;\n /** When true, the relation can only target users flagged as minors. */\n requires_minor?: boolean;\n /** When true, the relation is symmetric (A→B implies B→A). */\n bidirectional?: boolean;\n}\n\n// ── Registration fields ──\n\nexport interface RegistrationFieldDefinition {\n /** Field key used as the form field name + in profile data. */\n key: string;\n /** Display label. */\n label: string;\n /** One of: text, email, phone, date, number, select, boolean, url, textarea. */\n field_type: string;\n required: boolean;\n show_on_register: boolean;\n /** Optional validation metadata — passed through to the UI. */\n validation?: Record<string, unknown>;\n}\n\nexport interface RegistrationConfig {\n /** Ordered list of custom registration fields. Declaring this replaces the full list. */\n fields: RegistrationFieldDefinition[];\n}\n\n// ── OAuth providers ──\n\nexport interface OAuthProviderDefinition {\n enabled: boolean;\n client_id: string;\n /** Prefer `{ env: \"VAR_NAME\" }` or `\"${env.VAR_NAME}\"`. */\n client_secret: SecretRef;\n scopes: string[];\n /** Only for `custom_oidc`. */\n discovery_url?: string;\n}\n\nexport interface OAuthProvidersConfig {\n google?: OAuthProviderDefinition;\n github?: OAuthProviderDefinition;\n okta?: OAuthProviderDefinition;\n custom_oidc?: OAuthProviderDefinition;\n}\n\n// ── Security ──\n\nexport interface PasswordPolicyDefinition {\n min_length: number;\n require_uppercase: boolean;\n require_number: boolean;\n require_special: boolean;\n}\n\nexport interface SessionConfigDefinition {\n access_token_ttl_secs: number;\n refresh_token_ttl_secs: number;\n max_sessions_per_user: number;\n require_email_verification: boolean;\n}\n\nexport interface SecurityConfig {\n password_policy?: PasswordPolicyDefinition;\n session?: SessionConfigDefinition;\n}\n\n// ── Branding ──\n\nexport interface BrandingConfig {\n app_name?: string;\n logo_url?: string;\n primary_color?: string;\n secondary_color?: string;\n welcome_message?: string;\n welcome_subtitle?: string;\n /** `\"centered\"`, `\"split-left\"`, `\"split-right\"`, or `\"fullscreen\"`. */\n layout?: string;\n background_image_url?: string;\n /** 0–100 percentage. */\n background_focal_point?: { x: number; y: number };\n background_gradient?: string;\n /** `\"light\"`, `\"dark\"`, or `\"auto\"`. */\n color_mode?: string;\n font_family?: string;\n terms_url?: string;\n privacy_url?: string;\n /** Raw CSS merged into the hosted auth pages. */\n custom_css?: string;\n}\n\n// ── Top-level shape ──\n\nexport interface AuthConfigBlock {\n resources?: ResourceDefinition[];\n groups?: GroupDefinition[];\n relations?: RelationTypeDefinition[];\n registration?: RegistrationConfig;\n oauth?: OAuthProvidersConfig;\n security?: SecurityConfig;\n branding?: BrandingConfig;\n}\n\nexport interface MaravillaConfig {\n /** All project-level auth settings. Every field is optional — partial adoption is supported. */\n auth?: AuthConfigBlock;\n /** Declarative database indexes (regular + vector). Reconciled upsert-only on deploy. */\n database?: DatabaseConfigBlock;\n /**\n * Declarative media transforms — each entry compiles into a synthetic\n * `storage.put` event handler that fans out the declared\n * `platform.media.transforms.*` calls (via `Promise.all`) for every\n * matching upload. See {@link TransformsConfig}.\n */\n transforms?: TransformsConfig;\n}\n\n// ── Database block ──\n//\n// Regular indexes speed up document reads on frequently-queried fields.\n// Vector indexes back hybrid semantic search via sqlite-vec. Both are\n// upsert-only — declaring an index in config creates it if missing,\n// updates metadata when safe, and never auto-deletes DB-only indexes.\n\n/** MongoDB-style key direction: `1` ascending, `-1` descending. */\nexport type IndexDirectionConfig = 1 | -1;\n\nexport interface DocumentIndexDeclaration {\n /** Collection the index lives on. */\n collection: string;\n /** Optional name; falls back to an auto-derived name. */\n name?: string;\n /**\n * Compound-index key shape. Array of `[field, direction]` tuples\n * preserves ordering, which matters for compound indexes.\n */\n keys: Array<[string, IndexDirectionConfig]> | Record<string, IndexDirectionConfig>;\n unique?: boolean;\n sparse?: boolean;\n /**\n * Partial-index predicate — restricted to inline-literal operators\n * (`$eq`, `$ne`, `$gt`/`$gte`/`$lt`/`$lte`, `$in`/`$nin`, `$exists`,\n * `$and`, `$or`). No `$regex` / `$where` / `$text`.\n */\n partial?: Record<string, unknown>;\n /** TTL in seconds. Requires a single-field index on a unix-seconds field. */\n expireAfterSeconds?: number;\n}\n\n/** Distance metric used by a vector index. */\nexport type VectorMetricConfig = 'cosine' | 'l2' | 'hamming';\n\n/** Storage precision for a vector index. */\nexport type VectorStorageConfig = 'float32' | 'int8' | 'bit';\n\nexport interface VectorIndexDeclaration {\n collection: string;\n field: string;\n dimensions: number;\n metric?: VectorMetricConfig;\n storage?: VectorStorageConfig;\n matryoshka?: boolean;\n multiVector?: boolean;\n}\n\nexport interface DatabaseConfigBlock {\n /** MongoDB-style secondary indexes. */\n indexes?: DocumentIndexDeclaration[];\n /** sqlite-vec-backed vector indexes. */\n vectorIndexes?: VectorIndexDeclaration[];\n}\n\n/**\n * Identity function that returns the config unchanged — exists purely so the\n * TypeScript compiler can infer `MaravillaConfig` and give you IntelliSense\n * on every field.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@maravilla-labs/platform/config';\n *\n * export default defineConfig({\n * auth: {\n * resources: [{ name: 'todos', title: 'Todos', actions: ['read', 'write'] }],\n * },\n * });\n * ```\n */\nexport function defineConfig(config: MaravillaConfig): MaravillaConfig {\n return config;\n}\n"],"mappings":";AA2RO,SAAS,aAAa,QAA0C;AACrE,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/config.ts"],"sourcesContent":["/**\n * @fileoverview Typed schema for `maravilla.config.{ts,yaml,json}` files.\n *\n * Declares your project's auth settings (resources, groups, relations,\n * registration fields, OAuth providers, security policy, branding) alongside\n * your code. The Maravilla adapter reads this at build time and reconciles\n * the settings into delivery on deploy.\n *\n * ```typescript\n * import { defineConfig } from '@maravilla-labs/platform/config';\n *\n * export default defineConfig({\n * auth: {\n * resources: [\n * { name: 'todos', title: 'Todos', actions: ['read', 'write'],\n * policy: 'auth.user_id == node.owner' },\n * ],\n * },\n * });\n * ```\n *\n * Omitted sections leave the DB alone — partial adoption is explicitly\n * supported. List-based sections (`resources`, `groups`, `relations`,\n * `oauth`) are upserted and never auto-delete DB-only entries. Singleton\n * sections (`registration`, `security`, `branding`) are replaced wholesale\n * when declared.\n */\n\n/**\n * String value that may either be a literal secret or a reference to an\n * environment variable on the **tenant** (resolved server-side at\n * reconcile time, never shipped plaintext in the manifest).\n *\n * Accepted forms:\n * - `\"literal-value\"` — inline (not recommended for real secrets)\n * - `\"${env.VAR_NAME}\"` — string-template form\n * - `{ env: \"VAR_NAME\" }` — object form\n */\nexport type SecretRef = string | { env: string };\n\nimport type { TransformsConfig } from './transforms.js';\nexport type { TransformsConfig, TransformsPatternSpec } from './transforms.js';\n\n// ── Resources + policies ──\n\n/**\n * The platform service this resource binds to. Used by the UI to offer\n * service-correct action presets and policy snippets, and by the reconciler\n * to validate that policies reference legal `node.*` fields for the service.\n *\n * Omit for legacy / cross-service umbrella resources — the runtime falls back\n * to matching purely by `name` (a name collision between e.g. a KV namespace\n * and a DB collection will silently share a policy, which is rarely desired).\n */\nexport type ResourceServiceType =\n | 'kv'\n | 'database'\n | 'realtime'\n | 'media'\n | 'vector'\n | 'storage'\n | 'queue'\n | 'push'\n | 'workflow'\n | 'transforms';\n\nexport interface ResourceDefinition {\n /** URL-safe slug. Used as the resource key in code (e.g. the KV namespace). */\n name: string;\n /** Human-readable title for the admin UI. */\n title: string;\n /** Optional longer description. */\n description?: string;\n /**\n * Which platform service this resource gates. When set, the reconciler\n * validates that the policy only references `node.*` fields legal for that\n * service (e.g. a `realtime` policy can't reference `node.collection`).\n */\n type?: ResourceServiceType;\n /** Actions this resource supports, e.g. `['read', 'write', 'delete']`. */\n actions: string[];\n /**\n * Optional raisin-rel policy expression. Evaluated on every KV/DB/\n * realtime/media op that targets this resource. Leave empty to skip\n * Layer 2 for this resource — tenant + owner isolation still applies.\n */\n policy?: string;\n /**\n * C+D read-filter (option ii). JSON object the runtime ANDs into the\n * caller's filter on `db.find` / `db.findOne`. Supports `$auth.<path>`\n * placeholder strings (e.g. `\"$auth.user_id\"`) substituted from the\n * caller's identity at request time. Allowed paths: `user_id`, `email`,\n * `is_admin`, `roles`.\n *\n * Independent of `policy` — `policy` gates writes and resolved-doc reads;\n * `read_filter` scopes which rows the caller can ever see.\n *\n * Example: `'{\"$or\":[{\"owner\":\"$auth.user_id\"},{\"public\":true}]}'`\n */\n read_filter?: string;\n}\n\n// ── Groups ──\n\nexport interface GroupPermissionDefinition {\n /** Must match a `ResourceDefinition.name`. */\n resource_name: string;\n /** Actions this group is granted on the resource. */\n actions: string[];\n}\n\nexport interface GroupDefinition {\n /** Unique group name per tenant. */\n name: string;\n /** Optional description for the admin UI. */\n description?: string;\n /** Resource permissions granted to the group. Replaces the group's current permissions when declared. */\n permissions?: GroupPermissionDefinition[];\n}\n\n// ── Relations ──\n\nexport interface RelationTypeDefinition {\n /** Uppercase identifier used in policies (`... VIA 'STEWARDS'`). */\n relation_name: string;\n /** Human-readable title. */\n title: string;\n description?: string;\n /** Grouping for the admin UI (e.g. `\"family\"`, `\"work\"`). */\n category?: string;\n icon?: string;\n color?: string;\n /** Name of the inverse relation type, if one exists. */\n inverse_relation_name?: string;\n /** When true, membership in this relation implies stewardship rights. */\n implies_stewardship?: boolean;\n /** When true, the relation can only target users flagged as minors. */\n requires_minor?: boolean;\n /** When true, the relation is symmetric (A→B implies B→A). */\n bidirectional?: boolean;\n}\n\n// ── Registration fields ──\n\nexport interface RegistrationFieldDefinition {\n /** Field key used as the form field name + in profile data. */\n key: string;\n /** Display label. */\n label: string;\n /** One of: text, email, phone, date, number, select, boolean, url, textarea. */\n field_type: string;\n required: boolean;\n show_on_register: boolean;\n /** Optional validation metadata — passed through to the UI. */\n validation?: Record<string, unknown>;\n}\n\nexport interface RegistrationConfig {\n /** Ordered list of custom registration fields. Declaring this replaces the full list. */\n fields: RegistrationFieldDefinition[];\n}\n\n// ── OAuth providers ──\n\nexport interface OAuthProviderDefinition {\n enabled: boolean;\n client_id: string;\n /** Prefer `{ env: \"VAR_NAME\" }` or `\"${env.VAR_NAME}\"`. */\n client_secret: SecretRef;\n scopes: string[];\n /** Only for `custom_oidc`. */\n discovery_url?: string;\n}\n\nexport interface OAuthProvidersConfig {\n google?: OAuthProviderDefinition;\n github?: OAuthProviderDefinition;\n okta?: OAuthProviderDefinition;\n custom_oidc?: OAuthProviderDefinition;\n}\n\n// ── Security ──\n\nexport interface PasswordPolicyDefinition {\n min_length: number;\n require_uppercase: boolean;\n require_number: boolean;\n require_special: boolean;\n}\n\nexport interface SessionConfigDefinition {\n access_token_ttl_secs: number;\n refresh_token_ttl_secs: number;\n max_sessions_per_user: number;\n require_email_verification: boolean;\n}\n\nexport interface SecurityConfig {\n password_policy?: PasswordPolicyDefinition;\n session?: SessionConfigDefinition;\n}\n\n// ── Branding ──\n\nexport interface BrandingConfig {\n app_name?: string;\n logo_url?: string;\n primary_color?: string;\n secondary_color?: string;\n welcome_message?: string;\n welcome_subtitle?: string;\n /** `\"centered\"`, `\"split-left\"`, `\"split-right\"`, or `\"fullscreen\"`. */\n layout?: string;\n background_image_url?: string;\n /** 0–100 percentage. */\n background_focal_point?: { x: number; y: number };\n background_gradient?: string;\n /** `\"light\"`, `\"dark\"`, or `\"auto\"`. */\n color_mode?: string;\n font_family?: string;\n terms_url?: string;\n privacy_url?: string;\n /** Raw CSS merged into the hosted auth pages. */\n custom_css?: string;\n}\n\n// ── Top-level shape ──\n\nexport interface AuthConfigBlock {\n resources?: ResourceDefinition[];\n groups?: GroupDefinition[];\n relations?: RelationTypeDefinition[];\n registration?: RegistrationConfig;\n oauth?: OAuthProvidersConfig;\n security?: SecurityConfig;\n branding?: BrandingConfig;\n}\n\nexport interface MaravillaConfig {\n /** All project-level auth settings. Every field is optional — partial adoption is supported. */\n auth?: AuthConfigBlock;\n /** Declarative database indexes (regular + vector). Reconciled upsert-only on deploy. */\n database?: DatabaseConfigBlock;\n /**\n * Declarative media transforms — each entry compiles into a synthetic\n * `storage.put` event handler that fans out the declared\n * `platform.media.transforms.*` calls (via `Promise.all`) for every\n * matching upload. See {@link TransformsConfig}.\n */\n transforms?: TransformsConfig;\n}\n\n// ── Database block ──\n//\n// Regular indexes speed up document reads on frequently-queried fields.\n// Vector indexes back hybrid semantic search via sqlite-vec. Both are\n// upsert-only — declaring an index in config creates it if missing,\n// updates metadata when safe, and never auto-deletes DB-only indexes.\n\n/** MongoDB-style key direction: `1` ascending, `-1` descending. */\nexport type IndexDirectionConfig = 1 | -1;\n\nexport interface DocumentIndexDeclaration {\n /** Collection the index lives on. */\n collection: string;\n /** Optional name; falls back to an auto-derived name. */\n name?: string;\n /**\n * Compound-index key shape. Array of `[field, direction]` tuples\n * preserves ordering, which matters for compound indexes.\n */\n keys: Array<[string, IndexDirectionConfig]> | Record<string, IndexDirectionConfig>;\n unique?: boolean;\n sparse?: boolean;\n /**\n * Partial-index predicate — restricted to inline-literal operators\n * (`$eq`, `$ne`, `$gt`/`$gte`/`$lt`/`$lte`, `$in`/`$nin`, `$exists`,\n * `$and`, `$or`). No `$regex` / `$where` / `$text`.\n */\n partial?: Record<string, unknown>;\n /** TTL in seconds. Requires a single-field index on a unix-seconds field. */\n expireAfterSeconds?: number;\n}\n\n/** Distance metric used by a vector index. */\nexport type VectorMetricConfig = 'cosine' | 'l2' | 'hamming';\n\n/** Storage precision for a vector index. */\nexport type VectorStorageConfig = 'float32' | 'int8' | 'bit';\n\nexport interface VectorIndexDeclaration {\n collection: string;\n field: string;\n dimensions: number;\n metric?: VectorMetricConfig;\n storage?: VectorStorageConfig;\n matryoshka?: boolean;\n multiVector?: boolean;\n}\n\nexport interface DatabaseConfigBlock {\n /** MongoDB-style secondary indexes. */\n indexes?: DocumentIndexDeclaration[];\n /** sqlite-vec-backed vector indexes. */\n vectorIndexes?: VectorIndexDeclaration[];\n}\n\n/**\n * Identity function that returns the config unchanged — exists purely so the\n * TypeScript compiler can infer `MaravillaConfig` and give you IntelliSense\n * on every field.\n *\n * @example\n * ```typescript\n * import { defineConfig } from '@maravilla-labs/platform/config';\n *\n * export default defineConfig({\n * auth: {\n * resources: [{ name: 'todos', title: 'Todos', actions: ['read', 'write'] }],\n * },\n * });\n * ```\n */\nexport function defineConfig(config: MaravillaConfig): MaravillaConfig {\n return config;\n}\n"],"mappings":";AAmUO,SAAS,aAAa,QAA0C;AACrE,SAAO;AACT;","names":[]}
package/dist/index.d.ts CHANGED
@@ -945,6 +945,201 @@ interface UpdateUserOptions {
945
945
  /** Profile data to merge */
946
946
  profile?: Record<string, any>;
947
947
  }
948
+ interface AuthGroup {
949
+ id: string;
950
+ name: string;
951
+ description: string | null;
952
+ permissions: string[];
953
+ member_count: number;
954
+ created_at: number;
955
+ updated_at: number;
956
+ }
957
+ interface CreateGroupOptions {
958
+ name: string;
959
+ description?: string;
960
+ permissions?: string[];
961
+ }
962
+ interface UpdateGroupOptions {
963
+ name?: string;
964
+ description?: string;
965
+ permissions?: string[];
966
+ }
967
+ interface GroupPermission {
968
+ resource_name: string;
969
+ actions: string[];
970
+ }
971
+ interface AuthCircle {
972
+ id: string;
973
+ name: string;
974
+ metadata: Record<string, any> | null;
975
+ member_count: number;
976
+ created_at: number;
977
+ updated_at: number;
978
+ }
979
+ interface CreateCircleOptions {
980
+ name: string;
981
+ metadata?: Record<string, any>;
982
+ }
983
+ interface UpdateCircleOptions {
984
+ name?: string;
985
+ metadata?: Record<string, any>;
986
+ }
987
+ interface AddCircleMemberOptions {
988
+ user_id: string;
989
+ relationship: string;
990
+ is_primary_contact?: boolean;
991
+ }
992
+ interface CircleMembership {
993
+ user_id: string;
994
+ email: string;
995
+ relationship: string;
996
+ is_primary_contact: boolean;
997
+ joined_at: number;
998
+ }
999
+ type ResourceServiceType = 'kv' | 'database' | 'realtime' | 'media' | 'vector' | 'storage' | 'queue' | 'push' | 'workflow' | 'transforms';
1000
+ interface Resource {
1001
+ id: string;
1002
+ resource_name: string;
1003
+ title: string;
1004
+ description: string | null;
1005
+ actions: string[];
1006
+ policy: string | null;
1007
+ service_type: ResourceServiceType | null;
1008
+ read_filter: string | null;
1009
+ created_at: number;
1010
+ updated_at: number;
1011
+ }
1012
+ interface CreateResourceOptions {
1013
+ resource_name: string;
1014
+ title: string;
1015
+ description?: string;
1016
+ actions?: string[];
1017
+ policy?: string;
1018
+ service_type?: ResourceServiceType;
1019
+ read_filter?: string;
1020
+ }
1021
+ interface UpdateResourceOptions {
1022
+ title?: string;
1023
+ description?: string;
1024
+ actions?: string[];
1025
+ policy?: string;
1026
+ service_type?: ResourceServiceType;
1027
+ read_filter?: string;
1028
+ }
1029
+ interface RelationType {
1030
+ id: string;
1031
+ relation_name: string;
1032
+ title: string;
1033
+ description: string | null;
1034
+ category: string;
1035
+ icon: string | null;
1036
+ color: string | null;
1037
+ inverse_relation_id: string | null;
1038
+ implies_stewardship: boolean;
1039
+ requires_minor: boolean;
1040
+ bidirectional: boolean;
1041
+ is_system: boolean;
1042
+ created_at: number;
1043
+ updated_at: number;
1044
+ }
1045
+ interface CreateRelationTypeOptions {
1046
+ relation_name: string;
1047
+ title: string;
1048
+ description?: string;
1049
+ category?: string;
1050
+ icon?: string;
1051
+ color?: string;
1052
+ inverse_relation_id?: string;
1053
+ implies_stewardship?: boolean;
1054
+ requires_minor?: boolean;
1055
+ bidirectional?: boolean;
1056
+ is_system?: boolean;
1057
+ }
1058
+ interface UpdateRelationTypeOptions {
1059
+ title?: string;
1060
+ description?: string;
1061
+ category?: string;
1062
+ icon?: string;
1063
+ color?: string;
1064
+ inverse_relation_id?: string;
1065
+ implies_stewardship?: boolean;
1066
+ requires_minor?: boolean;
1067
+ bidirectional?: boolean;
1068
+ }
1069
+ interface AuthConfig {
1070
+ fields: AuthField[];
1071
+ oauth_providers: any[];
1072
+ branding: Record<string, any>;
1073
+ password_policy: Record<string, any>;
1074
+ session_config: Record<string, any>;
1075
+ }
1076
+ type DelegationMode = 'full' | 'scoped';
1077
+ type StewardshipStatus = 'active' | 'suspended' | 'revoked' | 'expired';
1078
+ interface ScopedPermission {
1079
+ resource: string;
1080
+ actions: string[];
1081
+ }
1082
+ interface StewardshipOverride {
1083
+ id: string;
1084
+ steward_id: string;
1085
+ ward_id: string;
1086
+ delegation_mode: DelegationMode;
1087
+ scoped_permissions: ScopedPermission[];
1088
+ valid_from: number | null;
1089
+ valid_until: number | null;
1090
+ status: StewardshipStatus;
1091
+ reason: string | null;
1092
+ source: string;
1093
+ source_circle_id: string | null;
1094
+ source_relation_type_id: string | null;
1095
+ created_at: number;
1096
+ updated_at: number;
1097
+ }
1098
+ interface CreateStewardshipOverrideOptions {
1099
+ steward_id: string;
1100
+ ward_id: string;
1101
+ delegation_mode?: DelegationMode;
1102
+ scoped_permissions?: ScopedPermission[];
1103
+ valid_from?: number;
1104
+ valid_until?: number;
1105
+ reason?: string;
1106
+ }
1107
+ interface StewardshipResolution {
1108
+ stewards: StewardshipOverride[];
1109
+ wards: StewardshipOverride[];
1110
+ }
1111
+ interface ActAsContext {
1112
+ steward_id: string;
1113
+ ward_id: string;
1114
+ delegation_mode: DelegationMode;
1115
+ scoped_permissions: ScopedPermission[];
1116
+ session_token: string;
1117
+ expires_at: number;
1118
+ }
1119
+ interface StewardshipAuditEntry {
1120
+ id: string;
1121
+ performed_by: string;
1122
+ on_behalf_of: string;
1123
+ action: string;
1124
+ resource: string | null;
1125
+ details: Record<string, any> | null;
1126
+ created_at: number;
1127
+ }
1128
+ /**
1129
+ * Sub-namespace exposed at `platform.auth.stewardship` mirroring the
1130
+ * runtime's `globalThis.platform.auth.stewardship.*` surface.
1131
+ */
1132
+ interface AuthStewardshipApi {
1133
+ resolve(userId: string): Promise<StewardshipResolution>;
1134
+ createOverride(opts: CreateStewardshipOverrideOptions): Promise<StewardshipOverride>;
1135
+ revoke(id: string): Promise<void>;
1136
+ checkPermission(stewardId: string, wardId: string, resource: string, action: string): Promise<boolean>;
1137
+ createActAs(stewardId: string, wardId: string): Promise<ActAsContext>;
1138
+ listAudit(userId: string, options?: {
1139
+ limit?: number;
1140
+ offset?: number;
1141
+ }): Promise<StewardshipAuditEntry[]>;
1142
+ }
948
1143
  /**
949
1144
  * Auth service for end-user authentication and user management.
950
1145
  *
@@ -1106,6 +1301,39 @@ interface AuthService {
1106
1301
  withAuth<T extends (request: Request & {
1107
1302
  user: AuthUser;
1108
1303
  }) => Promise<Response>>(handler: T): (request: Request) => Promise<Response>;
1304
+ createGroup(options: CreateGroupOptions): Promise<AuthGroup>;
1305
+ listGroups(): Promise<AuthGroup[]>;
1306
+ getGroup(groupId: string): Promise<AuthGroup | null>;
1307
+ updateGroup(groupId: string, options: UpdateGroupOptions): Promise<AuthGroup>;
1308
+ deleteGroup(groupId: string): Promise<void>;
1309
+ addUserToGroup(userId: string, groupId: string): Promise<void>;
1310
+ removeUserFromGroup(userId: string, groupId: string): Promise<void>;
1311
+ getUserGroups(userId: string): Promise<AuthGroup[]>;
1312
+ getGroupMembers(groupId: string): Promise<AuthUser[]>;
1313
+ getGroupPermissions(groupId: string): Promise<GroupPermission[]>;
1314
+ setGroupPermissions(groupId: string, permissions: GroupPermission[]): Promise<void>;
1315
+ createCircle(options: CreateCircleOptions): Promise<AuthCircle>;
1316
+ listCircles(): Promise<AuthCircle[]>;
1317
+ getCircle(circleId: string): Promise<AuthCircle | null>;
1318
+ updateCircle(circleId: string, options: UpdateCircleOptions): Promise<AuthCircle>;
1319
+ deleteCircle(circleId: string): Promise<void>;
1320
+ addCircleMember(circleId: string, options: AddCircleMemberOptions): Promise<void>;
1321
+ removeCircleMember(circleId: string, userId: string): Promise<void>;
1322
+ getCircleMembers(circleId: string): Promise<CircleMembership[]>;
1323
+ getUserCircles(userId: string): Promise<AuthCircle[]>;
1324
+ createResource(options: CreateResourceOptions): Promise<Resource>;
1325
+ listResources(): Promise<Resource[]>;
1326
+ updateResource(resourceId: string, options: UpdateResourceOptions): Promise<Resource>;
1327
+ deleteResource(resourceId: string): Promise<void>;
1328
+ createRelationType(options: CreateRelationTypeOptions): Promise<RelationType>;
1329
+ listRelationTypes(): Promise<RelationType[]>;
1330
+ updateRelationType(id: string, options: UpdateRelationTypeOptions): Promise<RelationType>;
1331
+ deleteRelationType(id: string): Promise<void>;
1332
+ getProfile(userId: string): Promise<Record<string, any>>;
1333
+ setProfile(userId: string, data: Record<string, any>): Promise<void>;
1334
+ getAuthConfig(): Promise<AuthConfig>;
1335
+ setAuthConfig(config: AuthConfig): Promise<void>;
1336
+ readonly stewardship: AuthStewardshipApi;
1109
1337
  /**
1110
1338
  * Explicitly bind the caller for the remainder of this request.
1111
1339
  * Pass a JWT to validate + bind, or `null` / `""` to clear.
@@ -1652,6 +1880,64 @@ declare class MediaRoom {
1652
1880
  private wireEvents;
1653
1881
  }
1654
1882
 
1883
+ /**
1884
+ * Per-request scope for the SDK's remote client. Mirrors the runtime's
1885
+ * `REQUEST_CTX` (a `tokio::task_local!` in Rust) so that
1886
+ * `platform.auth.setCurrentUser(token)`, `getCurrentUser()`, and `can()`
1887
+ * — plus future per-request state like the Layer-2 policy toggle —
1888
+ * have a place to live when the SDK is running outside the runtime
1889
+ * (Vite SSR, Node.js HTTP servers, edge workers that expose Node APIs).
1890
+ *
1891
+ * Implementation: Node's `AsyncLocalStorage`. Tenant code wraps each
1892
+ * inbound request with `runWithRequest(async () => { ... })` so the
1893
+ * store stays scoped to the request's async chain. `setCurrentUser`
1894
+ * / `can` read and write that store; if a tenant forgets to wrap, the
1895
+ * methods either no-op (set) or throw a clear error (get/can).
1896
+ */
1897
+
1898
+ interface RequestStore {
1899
+ /** Bound access-token JWT (set by `auth.setCurrentUser`). */
1900
+ token?: string;
1901
+ /** Bound user (cached so `getCurrentUser` doesn't re-validate). */
1902
+ user?: AuthUser;
1903
+ /** Whether Layer-2 policy enforcement is enabled for this request. */
1904
+ policyEnabled: boolean;
1905
+ }
1906
+ /**
1907
+ * Wrap a function in a fresh request scope. **Rarely needed** — the
1908
+ * Maravilla Vite plugin (`@maravilla-labs/vite-plugin`) auto-opens a
1909
+ * scope around every inbound dev HTTP request, so tenant code
1910
+ * (SvelteKit `hooks.server.ts`, RR/Remix loaders, etc.) reaches
1911
+ * `setCurrentUser/getCurrentUser/can` with a scope already active.
1912
+ *
1913
+ * Reach for `runWithRequest` only when the SDK runs **outside** an
1914
+ * HTTP request: standalone Node scripts, test fixtures, custom
1915
+ * servers that don't go through Vite. Inside an active scope,
1916
+ * `platform.auth.setCurrentUser/getCurrentUser/can` operate on a
1917
+ * per-request store keyed by Node's `AsyncLocalStorage`.
1918
+ *
1919
+ * @example
1920
+ * ```ts
1921
+ * // Test fixture that needs to bind a user before exercising the SDK
1922
+ * await runWithRequest(async () => {
1923
+ * await getPlatform().auth.setCurrentUser(testToken);
1924
+ * const result = await getPlatform().env.DB.find('users', {});
1925
+ * expect(result).toEqual(...);
1926
+ * });
1927
+ * ```
1928
+ */
1929
+ declare function runWithRequest<T>(fn: () => Promise<T> | T): Promise<T>;
1930
+ /**
1931
+ * Read the current request's store, if any. Returns undefined when
1932
+ * called outside a `runWithRequest` scope. Used by `RemoteAuthService`
1933
+ * and (future) other Remote* services to source per-request state.
1934
+ *
1935
+ * Note: the `als` may not yet be initialised when this is called; in
1936
+ * that case the function returns undefined synchronously. Subsequent
1937
+ * `runWithRequest` calls will populate it.
1938
+ */
1939
+ declare function getCurrentRequestStore(): RequestStore | undefined;
1940
+
1655
1941
  /**
1656
1942
  * @fileoverview Maravilla Platform SDK
1657
1943
  *
@@ -1772,4 +2058,4 @@ declare function getPlatform(options?: {
1772
2058
  */
1773
2059
  declare function clearPlatformCache(): void;
1774
2060
 
1775
- export { type AuthCaller, type AuthField, type AuthService, type AuthSession, type AuthUser, type Database, type DbFindOptions, type IndexDescriptor, type IndexDirection, type IndexKind, type IndexSpec, type KvListResult, type KvNamespace, type ListScheduledFilter, type LoginOptions, MediaLocalParticipant, type MediaParticipant, type MediaParticipantInfo, MediaRoom, MediaRoomEvent, type MediaRoomInfo, type MediaRoomInfoSettings, type MediaRoomOptions, type MediaService, type MediaTokenResult, type MediaTrackPublication, type NotificationPayload, type Platform, type PlatformEnv, type PolicyService, type PresenceMember, type PresenceService, type PublicPushConfig, type PushService, type PushTarget, type QueueStats, RealtimeClient, type RealtimeClientOptions, type RealtimeEvent, type RealtimeService, type RegisterOptions, RemoteMediaService, type ScheduleOptions, type ScheduledJob, type SendReport, type Storage, type StoragePutStreamSource, type StoredPushSubscription, type SubscriptionCounts, type TrackKind, type TrackSource, type UpdateUserOptions, type UserListFilter, type UserListResponse, type VectorAggregation, type VectorIndexDescriptor, type VectorIndexSpec, type VectorMetric, type VectorQuery, type VectorQueryMode, type VectorQueryWithFilter, type VectorSearchHit, type VectorStorage, type VideoResolution, type WorkflowHandle, type WorkflowRun, type WorkflowRunStatus, type WorkflowStepKind, type WorkflowStepRecord, type Workflows, attachTrack, clearPlatformCache, detachTrack, getPlatform };
2061
+ export { type ActAsContext, type AddCircleMemberOptions, type AuthCaller, type AuthCircle, type AuthConfig, type AuthField, type AuthGroup, type AuthService, type AuthSession, type AuthStewardshipApi, type AuthUser, type CircleMembership, type CreateCircleOptions, type CreateGroupOptions, type CreateRelationTypeOptions, type CreateResourceOptions, type CreateStewardshipOverrideOptions, type Database, type DbFindOptions, type DelegationMode, type GroupPermission, type IndexDescriptor, type IndexDirection, type IndexKind, type IndexSpec, type KvListResult, type KvNamespace, type ListScheduledFilter, type LoginOptions, MediaLocalParticipant, type MediaParticipant, type MediaParticipantInfo, MediaRoom, MediaRoomEvent, type MediaRoomInfo, type MediaRoomInfoSettings, type MediaRoomOptions, type MediaService, type MediaTokenResult, type MediaTrackPublication, type NotificationPayload, type Platform, type PlatformEnv, type PolicyService, type PresenceMember, type PresenceService, type PublicPushConfig, type PushService, type PushTarget, type QueueStats, RealtimeClient, type RealtimeClientOptions, type RealtimeEvent, type RealtimeService, type RegisterOptions, type RelationType, RemoteMediaService, type RequestStore, type Resource, type ResourceServiceType, type ScheduleOptions, type ScheduledJob, type ScopedPermission, type SendReport, type StewardshipAuditEntry, type StewardshipOverride, type StewardshipResolution, type StewardshipStatus, type Storage, type StoragePutStreamSource, type StoredPushSubscription, type SubscriptionCounts, type TrackKind, type TrackSource, type UpdateCircleOptions, type UpdateGroupOptions, type UpdateRelationTypeOptions, type UpdateResourceOptions, type UpdateUserOptions, type UserListFilter, type UserListResponse, type VectorAggregation, type VectorIndexDescriptor, type VectorIndexSpec, type VectorMetric, type VectorQuery, type VectorQueryMode, type VectorQueryWithFilter, type VectorSearchHit, type VectorStorage, type VideoResolution, type WorkflowHandle, type WorkflowRun, type WorkflowRunStatus, type WorkflowStepKind, type WorkflowStepRecord, type Workflows, attachTrack, clearPlatformCache, detachTrack, getCurrentRequestStore, getPlatform, runWithRequest };