slotlock 0.6.2 → 0.7.0

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 (100) hide show
  1. package/CHANGELOG.md +492 -0
  2. package/CONTRIBUTING.md +12 -5
  3. package/README.md +50 -1544
  4. package/SECURITY.md +5 -2
  5. package/SPEC.md +1 -1
  6. package/agent-server.d.ts +160 -8
  7. package/agent-server.js +560 -49
  8. package/agent-store-backend.d.ts +39 -7
  9. package/agent-store-backend.js +1439 -104
  10. package/api-keys.d.ts +69 -3
  11. package/api-keys.js +218 -29
  12. package/application-api.d.ts +59 -6
  13. package/application-api.js +842 -39
  14. package/approvals.d.ts +88 -0
  15. package/approvals.js +293 -0
  16. package/assistant.d.ts +58 -27
  17. package/assistant.js +151 -53
  18. package/billing.d.ts +114 -0
  19. package/billing.js +258 -0
  20. package/booking-rules.d.ts +30 -41
  21. package/booking-rules.js +17 -25
  22. package/change-watch.d.ts +1 -0
  23. package/change-watch.js +1 -1
  24. package/cli.js +3 -4
  25. package/config.d.ts +42 -6
  26. package/config.js +114 -7
  27. package/dashboard-icon.d.ts +1 -0
  28. package/dashboard-icon.js +5 -0
  29. package/dashboard.d.ts +203 -7
  30. package/dashboard.js +1558 -64
  31. package/ddl.d.ts +67 -35
  32. package/ddl.js +2732 -162
  33. package/engine.d.ts +6 -9
  34. package/engine.js +5 -9
  35. package/event-feed.d.ts +53 -35
  36. package/event-feed.js +201 -64
  37. package/event-schema.js +6 -9
  38. package/hooks.d.ts +2 -4
  39. package/hooks.js +2 -4
  40. package/ical-worker-thread.js +3 -4
  41. package/ical-worker.d.ts +8 -10
  42. package/ical-worker.js +7 -9
  43. package/index.d.ts +15 -4
  44. package/index.js +8 -2
  45. package/interop.js +1 -4
  46. package/maintenance.d.ts +24 -10
  47. package/maintenance.js +59 -28
  48. package/mcp-app.d.ts +7 -9
  49. package/mcp-app.js +7 -9
  50. package/mcp-modern.d.ts +14 -16
  51. package/mcp-modern.js +23 -27
  52. package/metrics.d.ts +41 -0
  53. package/metrics.js +22 -1
  54. package/node-server.d.ts +9 -9
  55. package/node-server.js +25 -34
  56. package/openapi.json +14675 -5957
  57. package/otel.d.ts +86 -0
  58. package/otel.js +273 -0
  59. package/overage.d.ts +33 -0
  60. package/overage.js +115 -0
  61. package/package-version.js +2 -4
  62. package/package.json +1 -1
  63. package/partner-billing.d.ts +81 -0
  64. package/partner-billing.js +333 -0
  65. package/partner-names.d.ts +8 -0
  66. package/partner-names.js +10 -0
  67. package/partners.d.ts +147 -0
  68. package/partners.js +375 -0
  69. package/plans.d.ts +92 -0
  70. package/plans.js +115 -0
  71. package/quotas.d.ts +108 -0
  72. package/quotas.js +258 -0
  73. package/rate-limit.d.ts +27 -2
  74. package/rate-limit.js +106 -23
  75. package/resource-profile.d.ts +135 -0
  76. package/resource-profile.js +263 -0
  77. package/rest-api.d.ts +15 -14
  78. package/rest-api.js +79 -15
  79. package/rules.d.ts +6 -7
  80. package/rules.js +30 -42
  81. package/sandbox.d.ts +70 -0
  82. package/sandbox.js +295 -0
  83. package/self-host.d.ts +46 -4
  84. package/self-host.js +990 -41
  85. package/slotlock.manifest.json +1 -1
  86. package/store.d.ts +482 -165
  87. package/store.js +1460 -484
  88. package/sync.d.ts +44 -59
  89. package/sync.js +325 -469
  90. package/teams.d.ts +25 -0
  91. package/teams.js +63 -0
  92. package/timezone.d.ts +25 -33
  93. package/timezone.js +50 -53
  94. package/types.d.ts +130 -57
  95. package/usage.d.ts +106 -0
  96. package/usage.js +238 -0
  97. package/webhooks.d.ts +22 -25
  98. package/webhooks.js +35 -40
  99. package/weekly-hours.d.ts +3 -0
  100. package/weekly-hours.js +1 -1
package/ddl.d.ts CHANGED
@@ -1,18 +1,17 @@
1
1
  /** The start of the message with which the deployment DDL refuses a `slotlock` schema. */
2
2
  export declare const SLOTLOCK_SCHEMA_CONTROL_REFUSAL = "Slotlock will not deploy into schema slotlock";
3
3
  /**
4
- * The version of the schema this release creates, recorded in `slotlock.schema_version` by every
5
- * migration. Releases up to 0.2 recorded nothing; 0.1 was version 1 and 0.2 version 2; 0.3 to 0.5
6
- * recorded 3. 0.6 is 4, so a 0.5 release refuses it before it changes anything: its DDL would put
7
- * back the trigger that names a coverage source by its guessable digest.
4
+ * The schema version this release creates, recorded in `slotlock.schema_version`. Up to 0.2
5
+ * recorded nothing (0.1 was 1, 0.2 was 2); 0.3 to 0.5 recorded 3. 0.6 is 4, so a 0.5 release
6
+ * refuses it rather than restoring the trigger that names a coverage source by its guessable
7
+ * digest.
8
8
  */
9
9
  export declare const SLOTLOCK_SCHEMA_VERSION = 4;
10
10
  /** The start of the message with which the deployment DDL refuses a schema a newer release migrated. */
11
11
  export declare const SLOTLOCK_SCHEMA_NEWER_REFUSAL = "Slotlock will not migrate a schema a newer release migrated";
12
12
  /**
13
- * What every migration checks before it changes anything, applySchema and applyTenantRls included
14
- * when they find nothing to change: that no other role controls the schema, then the server version
15
- * and the schema version. Run with search_path pinned, as the DDL pins it.
13
+ * What every migration checks before changing anything, even when it finds nothing to change: no
14
+ * other role controls the schema, then server and schema version. Run with search_path pinned.
16
15
  */
17
16
  export declare const SLOTLOCK_DEPLOYMENT_CHECKS = "DO $slotlock_schema_control$\nDECLARE\n refusals text[];\nBEGIN\n SELECT pg_catalog.array_agg(refusal.reason ORDER BY refusal.reason)\n INTO refusals\n FROM (\n SELECT 'schema slotlock is owned by ' || owned_by.rolname AS reason\n FROM pg_catalog.pg_namespace ns\n JOIN pg_catalog.pg_roles owned_by ON owned_by.oid = ns.nspowner\n WHERE ns.nspname = 'slotlock'\n AND owned_by.rolname <> CURRENT_USER AND NOT owned_by.rolsuper\n UNION\n SELECT COALESCE(grantee_role.rolname, 'PUBLIC') || ' can create objects in schema slotlock'\n FROM pg_catalog.pg_namespace ns\n CROSS JOIN LATERAL pg_catalog.aclexplode(ns.nspacl) acl\n LEFT JOIN pg_catalog.pg_roles grantee_role ON grantee_role.oid = acl.grantee\n WHERE ns.nspname = 'slotlock'\n AND acl.privilege_type = 'CREATE'\n AND acl.grantee <> ns.nspowner\n AND (acl.grantee = 0\n OR (grantee_role.rolname <> CURRENT_USER AND NOT grantee_role.rolsuper))\n UNION\n SELECT ident.type || ' ' || ident.identity || ' is owned by ' || owned_by.rolname\n FROM pg_catalog.pg_shdepend owned\n JOIN pg_catalog.pg_roles owned_by ON owned_by.oid = owned.refobjid\n CROSS JOIN LATERAL pg_catalog.pg_identify_object(owned.classid, owned.objid, owned.objsubid) ident\n WHERE owned.dbid = (SELECT db.oid FROM pg_catalog.pg_database db\n WHERE db.datname = pg_catalog.current_database())\n AND owned.deptype = 'o'\n AND owned.refclassid = 'pg_catalog.pg_authid'::pg_catalog.regclass\n AND owned_by.rolname <> CURRENT_USER AND NOT owned_by.rolsuper\n AND ident.schema = 'slotlock'\n UNION\n SELECT 'trigger ' || trg.tgname || ' on slotlock.' || rel.relname || ' runs '\n || trg.tgfoid::pg_catalog.regprocedure::pg_catalog.text\n || ', owned by ' || owned_by.rolname\n FROM pg_catalog.pg_trigger trg\n JOIN pg_catalog.pg_class rel ON rel.oid = trg.tgrelid\n JOIN pg_catalog.pg_namespace ns ON ns.oid = rel.relnamespace\n JOIN pg_catalog.pg_proc fn ON fn.oid = trg.tgfoid\n JOIN pg_catalog.pg_roles owned_by ON owned_by.oid = fn.proowner\n WHERE ns.nspname = 'slotlock'\n AND NOT trg.tgisinternal\n AND owned_by.rolname <> CURRENT_USER AND NOT owned_by.rolsuper\n UNION\n SELECT COALESCE(grantee_role.rolname, 'PUBLIC') || ' can create triggers on slotlock.'\n || rel.relname\n FROM pg_catalog.pg_class rel\n JOIN pg_catalog.pg_namespace ns ON ns.oid = rel.relnamespace\n CROSS JOIN LATERAL pg_catalog.aclexplode(rel.relacl) acl\n LEFT JOIN pg_catalog.pg_roles grantee_role ON grantee_role.oid = acl.grantee\n WHERE ns.nspname = 'slotlock'\n AND acl.privilege_type = 'TRIGGER'\n AND acl.grantee <> rel.relowner\n AND (acl.grantee = 0\n OR (grantee_role.rolname <> CURRENT_USER AND NOT grantee_role.rolsuper))\n UNION\n SELECT 'extension ' || ext.extname || ' in schema slotlock is owned by ' || owned_by.rolname\n FROM pg_catalog.pg_extension ext\n JOIN pg_catalog.pg_namespace ns ON ns.oid = ext.extnamespace\n JOIN pg_catalog.pg_roles owned_by ON owned_by.oid = ext.extowner\n WHERE ns.nspname = 'slotlock'\n AND owned_by.rolname <> CURRENT_USER AND NOT owned_by.rolsuper\n ) refusal;\n IF refusals IS NOT NULL THEN\n RAISE EXCEPTION 'Slotlock will not deploy into schema slotlock: another role controls it'\n USING ERRCODE = 'insufficient_privilege',\n DETAIL = pg_catalog.to_jsonb(refusals)::pg_catalog.text,\n HINT = 'The deployment role must own schema slotlock and every object in it, and no other role may create objects in it.';\n END IF;\nEND\n$slotlock_schema_control$;\nDO $slotlock_schema_preconditions$\nDECLARE\n installed integer;\nBEGIN\n IF pg_catalog.current_setting('server_version_num')::integer < 160000 THEN\n RAISE EXCEPTION 'Slotlock needs PostgreSQL 16 or later; this server is %',\n pg_catalog.current_setting('server_version')\n USING ERRCODE = 'feature_not_supported';\n END IF;\n IF pg_catalog.to_regclass('slotlock.schema_version') IS NOT NULL THEN\n EXECUTE 'SELECT version FROM slotlock.schema_version WHERE singleton' INTO installed;\n IF installed > 4 THEN\n RAISE EXCEPTION 'Slotlock will not migrate a schema a newer release migrated (version %; this release is version 4)', installed\n USING ERRCODE = 'object_not_in_prerequisite_state',\n HINT = 'Migrate and serve it with the release that migrated it, or a later one.';\n END IF;\n END IF;\nEND\n$slotlock_schema_preconditions$;\n";
18
17
  /** Active (unrevoked, unexpired) API keys one tenant may hold. */
@@ -23,19 +22,19 @@ export declare const SLOTLOCK_API_KEY_RETAINED_LIMIT = 1000;
23
22
  * The tables behind API keys. No role but their owner holds a right on them; they are reached only
24
23
  * through SLOTLOCK_API_KEY_FUNCTIONS.
25
24
  */
26
- export declare const SLOTLOCK_API_KEY_TABLES: readonly ["api_keys", "api_key_retired_digests"];
25
+ export declare const SLOTLOCK_API_KEY_TABLES: readonly ["api_keys", "api_key_retired_digests", "api_key_resource_scopes", "api_key_limits"];
27
26
  /**
28
27
  * The SECURITY DEFINER functions through which the serving role reaches API keys, by signature.
29
28
  * They run as the deployment role, which owns the tables.
30
29
  */
31
- export declare const SLOTLOCK_API_KEY_FUNCTIONS: readonly ["slotlock.create_api_key(text, text, text, bytea, text[], timestamptz, text)", "slotlock.list_api_keys(text)", "slotlock.rotate_api_key(text, uuid, text, bytea)", "slotlock.revoke_api_key(text, uuid)", "slotlock.authenticate_api_key(bytea)", "slotlock.erase_api_keys(text)"];
30
+ export declare const SLOTLOCK_API_KEY_FUNCTIONS: readonly ["slotlock.create_api_key(text, text, text, bytea, text[], timestamptz, text)", "slotlock.list_api_keys(text)", "slotlock.rotate_api_key(text, uuid, text, bytea)", "slotlock.revoke_api_key(text, uuid)", "slotlock.authenticate_api_key(bytea)", "slotlock.erase_api_keys(text)", "slotlock.set_api_key_resource_scope(text, uuid, text[], text[])", "slotlock.authenticate_scoped_api_key(bytea)", "slotlock.list_api_key_resource_scopes(text)", "slotlock.set_api_key_limits(text, uuid, integer, integer, integer, boolean)", "slotlock.list_api_key_limits(text)", "slotlock.authenticate_limited_api_key(bytea)"];
32
31
  /**
33
32
  * The table behind the dashboard's shared records (dashboard.ts). No role but its owner holds a
34
33
  * right on it; it is reached only through SLOTLOCK_DASHBOARD_FUNCTIONS.
35
34
  */
36
- export declare const SLOTLOCK_DASHBOARD_TABLES: readonly ["dashboard_tokens"];
35
+ export declare const SLOTLOCK_DASHBOARD_TABLES: readonly ["dashboard_tokens", "dashboard_organizations"];
37
36
  /** The SECURITY DEFINER functions through which the serving role reaches the dashboard's records. */
38
- export declare const SLOTLOCK_DASHBOARD_FUNCTIONS: readonly ["slotlock.use_dashboard_token(text, bytea, timestamptz, bytea)", "slotlock.dashboard_session_ended(bytea, timestamptz)"];
37
+ export declare const SLOTLOCK_DASHBOARD_FUNCTIONS: readonly ["slotlock.use_dashboard_token(text, bytea, timestamptz, bytea)", "slotlock.dashboard_session_ended(bytea, timestamptz)", "slotlock.enabled_organizations(text)", "slotlock.enable_organization(text, text, text)", "slotlock.disable_organization(text, text)"];
39
38
  /** Live form records one person may leave in the dashboard's records (12 hours of forms). */
40
39
  export declare const SLOTLOCK_DASHBOARD_FORM_LIMIT = 1000;
41
40
  /** The table that records which release migrated the schema (SLOTLOCK_SCHEMA_VERSION). */
@@ -43,21 +42,49 @@ export declare const SLOTLOCK_SCHEMA_TABLES: readonly ["schema_version"];
43
42
  /** The SECURITY DEFINER function through which a server reads the version it is serving. */
44
43
  export declare const SLOTLOCK_SCHEMA_FUNCTIONS: readonly ["slotlock.installed_schema_version()"];
45
44
  /** The table of suspended tenants: they may read, and write nothing (store.ts withTenant). */
46
- export declare const SLOTLOCK_TENANT_ADMIN_TABLES: readonly ["tenant_suspensions", "webhook_tenants", "rate_buckets", "assistant_tenants"];
45
+ export declare const SLOTLOCK_TENANT_ADMIN_TABLES: readonly ["tenant_suspensions", "tenant_plans", "plan_defaults", "usage_daily", "usage_flushes", "usage_cursors", "usage_meter_start", "usage_notices", "overage_reports", "webhook_tenants", "rate_buckets", "assistant_tenants", "maintenance_tenants"];
47
46
  /**
48
47
  * The SECURITY DEFINER functions through which a server checks a tenant's suspension and erases a
49
48
  * tenant, by signature.
50
49
  */
51
- export declare const SLOTLOCK_TENANT_ADMIN_FUNCTIONS: readonly ["slotlock.tenant_suspended(text)", "slotlock.erase_tenant(text)", "slotlock.register_webhook_tenant(text)", "slotlock.webhook_tenants(text)", "slotlock.unregister_webhook_tenant(text)", "slotlock.take_rate_token(text, double precision, double precision)", "slotlock.register_assistant_tenant(text, timestamptz)", "slotlock.sweep_assistant_conversations(integer)"];
50
+ export declare const SLOTLOCK_TENANT_ADMIN_FUNCTIONS: readonly ["slotlock.tenant_suspended(text)", "slotlock.erase_tenant(text)", "slotlock.register_webhook_tenant(text)", "slotlock.webhook_tenants(text)", "slotlock.unregister_webhook_tenant(text)", "slotlock.take_rate_token(text, double precision, double precision)", "slotlock.register_assistant_tenant(text, timestamptz)", "slotlock.sweep_assistant_conversations(integer)", "slotlock.list_maintenance_tenant()", "slotlock.maintenance_tenants(text)", "slotlock.tenant_plan(text)", "slotlock.set_tenant_plan(text, text, text, integer, integer, integer, text, text, timestamptz)", "slotlock.plan_default()", "slotlock.enrol_tenant_plan(text)", "slotlock.record_usage(uuid, jsonb)", "slotlock.roll_up_usage(text, integer)", "slotlock.tenant_usage(text, date, date)", "slotlock.tenant_quota_usage(text, date)", "slotlock.note_usage_threshold(text, date, text, integer, bigint, bigint)", "slotlock.tenant_plan_quotas(text)", "slotlock.reset_test_tenant(text)"];
51
+ /** The functions usage metering runs (SLOTLOCK_USAGE=on): serve checks it may, before it starts. */
52
+ export declare const SLOTLOCK_USAGE_FUNCTIONS: readonly ["slotlock.record_usage(uuid, jsonb)", "slotlock.roll_up_usage(text, integer)", "slotlock.tenant_usage(text, date, date)"];
53
+ /** The functions quotas run (SLOTLOCK_QUOTAS=on, quotas.ts): serve checks it may, before it starts. */
54
+ export declare const SLOTLOCK_QUOTA_FUNCTIONS: readonly ["slotlock.tenant_plan(text)", "slotlock.tenant_quota_usage(text, date)", "slotlock.note_usage_threshold(text, date, text, integer, bigint, bigint)"];
55
+ /** What a plan's monthly quotas count (quotas.ts): operations run and bookings made. */
56
+ export declare const SLOTLOCK_QUOTA_METRICS: readonly ["operations", "bookings"];
57
+ /** The shares of a quota, in percent, at which a tenant is told once a month (usage.threshold_reached). */
58
+ export declare const SLOTLOCK_QUOTA_NOTICE_PERCENTS: readonly [80, 100];
59
+ /** The most bookings past the roll-up cursor one quota read counts: more than any plan allows. */
60
+ export declare const SLOTLOCK_QUOTA_UNROLLED_LIMIT = 100000;
52
61
  /**
53
- * Functions only the deployment role runs: suspending and lifting a suspension. No other role is
54
- * granted them, so a serving role cannot lift a suspension.
62
+ * What usage.ts meters, per tenant and day: operations run, bookings and holds committed, webhook
63
+ * deliveries accepted, messages to the dashboard assistant, and resources held (a count each day, not
64
+ * a sum).
55
65
  */
56
- export declare const SLOTLOCK_OPERATOR_FUNCTIONS: readonly ["slotlock.suspend_tenant(text, text)", "slotlock.unsuspend_tenant(text)"];
66
+ export declare const SLOTLOCK_USAGE_METRICS: readonly ["operations", "bookings", "holds", "webhook_deliveries", "assistant_messages", "resources"];
67
+ /** The metrics a server counts and records (slotlock.record_usage); the rest the database counts. */
68
+ export declare const SLOTLOCK_RECORDED_USAGE_METRICS: readonly ["operations", "webhook_deliveries", "assistant_messages"];
69
+ /** Days a tenant's daily usage is kept: a yearly plan, and a month for disputes after it. */
70
+ export declare const SLOTLOCK_USAGE_RETENTION_DAYS = 400;
71
+ /**
72
+ * Functions only the deployment role runs: suspending and lifting a suspension, and setting the
73
+ * hosted plan every tenant without one of its own is on. No other role is granted them, so a serving
74
+ * role cannot lift a suspension or change the default plan.
75
+ */
76
+ export declare const SLOTLOCK_OPERATOR_FUNCTIONS: readonly ["slotlock.suspend_tenant(text, text)", "slotlock.unsuspend_tenant(text)", "slotlock.set_plan_default(text, integer, integer, integer, timestamptz)"];
57
77
  /** Every SECURITY DEFINER function the serving role may execute, by signature. */
58
- export declare const SLOTLOCK_DEFINER_FUNCTIONS: readonly ("slotlock.authenticate_api_key(bytea)" | "slotlock.create_api_key(text, text, text, bytea, text[], timestamptz, text)" | "slotlock.dashboard_session_ended(bytea, timestamptz)" | "slotlock.erase_api_keys(text)" | "slotlock.erase_tenant(text)" | "slotlock.installed_schema_version()" | "slotlock.list_api_keys(text)" | "slotlock.register_assistant_tenant(text, timestamptz)" | "slotlock.register_webhook_tenant(text)" | "slotlock.revoke_api_key(text, uuid)" | "slotlock.rotate_api_key(text, uuid, text, bytea)" | "slotlock.sweep_assistant_conversations(integer)" | "slotlock.take_rate_token(text, double precision, double precision)" | "slotlock.tenant_suspended(text)" | "slotlock.unregister_webhook_tenant(text)" | "slotlock.use_dashboard_token(text, bytea, timestamptz, bytea)" | "slotlock.webhook_tenants(text)")[];
78
+ /**
79
+ * Partner accounts (RFC 0003 part 4): what the serving role may call for a partner key and the
80
+ * partner API. A partner, its keys and its contract are made by the schema owner (`slotlock partner`).
81
+ */
82
+ export declare const SLOTLOCK_PARTNER_FUNCTIONS: readonly ["slotlock.partner_tenant_blocked(text)", "slotlock.authenticate_partner_key(bytea)", "slotlock.partner_contract(text)", "slotlock.put_partner_account(text, text, text)", "slotlock.list_partner_accounts(text)", "slotlock.get_partner_account(text, text)", "slotlock.set_partner_account_suspended(text, text, boolean, text)", "slotlock.partner_usage(text, date, date, text)", "slotlock.partner_account_tenant(text, text)", "slotlock.record_partner_reconciliation(text, date, integer, integer, numeric)"];
83
+ /** The partner tables: owner-only, reached through SLOTLOCK_PARTNER_FUNCTIONS. */
84
+ export declare const SLOTLOCK_PARTNER_TABLES: readonly ["partners", "partner_keys", "partner_accounts", "partner_invoices", "partner_month_closes", "partner_erased_usage", "partner_reconciliations"];
85
+ export declare const SLOTLOCK_DEFINER_FUNCTIONS: readonly ("slotlock.authenticate_api_key(bytea)" | "slotlock.authenticate_limited_api_key(bytea)" | "slotlock.authenticate_partner_key(bytea)" | "slotlock.authenticate_scoped_api_key(bytea)" | "slotlock.create_api_key(text, text, text, bytea, text[], timestamptz, text)" | "slotlock.dashboard_session_ended(bytea, timestamptz)" | "slotlock.disable_organization(text, text)" | "slotlock.enable_organization(text, text, text)" | "slotlock.enabled_organizations(text)" | "slotlock.enrol_tenant_plan(text)" | "slotlock.erase_api_keys(text)" | "slotlock.erase_tenant(text)" | "slotlock.get_partner_account(text, text)" | "slotlock.installed_schema_version()" | "slotlock.list_api_key_limits(text)" | "slotlock.list_api_key_resource_scopes(text)" | "slotlock.list_api_keys(text)" | "slotlock.list_maintenance_tenant()" | "slotlock.list_partner_accounts(text)" | "slotlock.maintenance_tenants(text)" | "slotlock.note_usage_threshold(text, date, text, integer, bigint, bigint)" | "slotlock.partner_account_tenant(text, text)" | "slotlock.partner_contract(text)" | "slotlock.partner_tenant_blocked(text)" | "slotlock.partner_usage(text, date, date, text)" | "slotlock.plan_default()" | "slotlock.put_partner_account(text, text, text)" | "slotlock.record_partner_reconciliation(text, date, integer, integer, numeric)" | "slotlock.record_usage(uuid, jsonb)" | "slotlock.register_assistant_tenant(text, timestamptz)" | "slotlock.register_webhook_tenant(text)" | "slotlock.reset_test_tenant(text)" | "slotlock.revoke_api_key(text, uuid)" | "slotlock.roll_up_usage(text, integer)" | "slotlock.rotate_api_key(text, uuid, text, bytea)" | "slotlock.set_api_key_limits(text, uuid, integer, integer, integer, boolean)" | "slotlock.set_api_key_resource_scope(text, uuid, text[], text[])" | "slotlock.set_partner_account_suspended(text, text, boolean, text)" | "slotlock.set_tenant_plan(text, text, text, integer, integer, integer, text, text, timestamptz)" | "slotlock.sweep_assistant_conversations(integer)" | "slotlock.take_rate_token(text, double precision, double precision)" | "slotlock.tenant_plan(text)" | "slotlock.tenant_plan_quotas(text)" | "slotlock.tenant_quota_usage(text, date)" | "slotlock.tenant_suspended(text)" | "slotlock.tenant_usage(text, date, date)" | "slotlock.unregister_webhook_tenant(text)" | "slotlock.use_dashboard_token(text, bytea, timestamptz, bytea)" | "slotlock.webhook_tenants(text)")[];
59
86
  /** Tables no role but their owner reads or writes, reached only through SLOTLOCK_DEFINER_FUNCTIONS. */
60
- export declare const SLOTLOCK_DEFINER_TABLES: readonly ("api_key_retired_digests" | "api_keys" | "assistant_tenants" | "dashboard_tokens" | "rate_buckets" | "schema_version" | "tenant_suspensions" | "webhook_tenants")[];
87
+ export declare const SLOTLOCK_DEFINER_TABLES: readonly ("api_key_limits" | "api_key_resource_scopes" | "api_key_retired_digests" | "api_keys" | "assistant_tenants" | "dashboard_organizations" | "dashboard_tokens" | "maintenance_tenants" | "overage_reports" | "partner_accounts" | "partner_erased_usage" | "partner_invoices" | "partner_keys" | "partner_month_closes" | "partner_reconciliations" | "partners" | "plan_defaults" | "rate_buckets" | "schema_version" | "tenant_plans" | "tenant_suspensions" | "usage_cursors" | "usage_daily" | "usage_flushes" | "usage_meter_start" | "usage_notices" | "webhook_tenants")[];
61
88
  /**
62
89
  * The advisory lock every server transaction for a tenant holds shared (store.ts withTenant), and
63
90
  * suspension and erasure take exclusively, keyed by this text's hashtextextended(…, 0).
@@ -68,16 +95,12 @@ export declare const SLOTLOCK_VALIDATION_DDL: string;
68
95
  /** Outbox ids one batch of the coverage-change rename reads (by primary key) in one transaction. */
69
96
  export declare const SLOTLOCK_COVERAGE_CHANGE_RENAME_BATCH = 5000;
70
97
  /**
71
- * One batch of the rename of coverage changes an earlier release wrote: of the outbox rows with ids
72
- * after `after` up to `head` (SQL expressions, bigint), the first `batch` by id, each `coverage.*`
73
- * one not yet in this release's shape gets its source's source_id as subject and `data.source_id`,
74
- * and loses `source` and `last_error`. Before 0.5.3 coverage.stale carried the source itself (an
75
- * iCalendar URL with a token, an address) and the error read from it; 0.5.3 named it by an unkeyed
76
- * digest anyone could confirm a guess against. A source deleted since is `src_redacted`: nothing
77
- * can match it any more, and a made-up id would look like a source the tenant could find. Selects
78
- * the last id read (`last`, null when there was none) and how many it renamed (`renamed`), `INTO`
79
- * `into` when given (PL/pgSQL). Rows in the new shape are left alone, so a batch run again changes
80
- * nothing.
98
+ * One batch of the rename of coverage changes an earlier release wrote: of the outbox rows after
99
+ * `after` up to `head` (bigint SQL expressions), the first `batch` by id; each `coverage.*` row not
100
+ * yet in shape gets its source_id as subject and `data.source_id`, and loses `source` and
101
+ * `last_error` (before 0.5.3 these carried the source itself, a URL with a token; 0.5.3's unkeyed
102
+ * digest could confirm a guess). A deleted source becomes `src_redacted`. Selects `last` (null when
103
+ * none) and `renamed`, `INTO` `into` when given. Idempotent.
81
104
  */
82
105
  export declare function slotlockCoverageChangeRenameSql(after: string, head: string, batch: string, into?: string): string;
83
106
  /** The whole deployment DDL, run in one transaction: the schema, then its constraints validated. */
@@ -93,14 +116,12 @@ export declare const SLOTLOCK_TENANT_CONTEXT_SETTING = "slotlock.tenant_ref";
93
116
  * `slotlock.rls_policy_contracts` and `slotlock.deployment_lifted_row_security` are
94
117
  * deployment-only and deliberately absent.
95
118
  */
96
- export declare const SLOTLOCK_TENANT_TABLES: readonly ["resources", "reservations", "reservation_tombstones", "reservation_conflict_archive", "calendar_events", "calendar_event_attendees", "calendar_event_reminders", "calendar_event_exceptions", "calendar_event_occurrences", "calendar_event_tombstones", "calendar_event_commands", "calendar_coverage", "hold_commands", "outbox", "outbox_pruned", "webhook_endpoints", "waitlist_entries", "booking_rule_defaults", "assistant_settings", "assistant_conversations"];
119
+ export declare const SLOTLOCK_TENANT_TABLES: readonly ["resources", "reservations", "reservation_tombstones", "reservation_conflict_archive", "calendar_events", "calendar_event_attendees", "calendar_event_reminders", "calendar_event_exceptions", "calendar_event_occurrences", "calendar_event_tombstones", "calendar_event_commands", "calendar_coverage", "hold_commands", "outbox", "outbox_pruned", "webhook_endpoints", "waitlist_entries", "booking_rule_defaults", "assistant_settings", "assistant_conversations", "locations", "resource_groups", "resource_group_members", "pool_settings", "composite_claims", "approval_policies", "approvals"];
97
120
  /**
98
- * Build the grants for the application role: USAGE on the `slotlock` schema, DML on the store's
99
- * tables and EXECUTE on the API key and dashboard functions. Nothing else: no ownership, DDL,
100
- * sequence, RLS-contract, API key or dashboard table access. The role must not be
101
- * able to leave forced RLS, itself or through a role it belongs to (`grantApplicationRole` refuses
102
- * the known ways out; these statements check nothing). Rerun after every `applySchema()`, since a
103
- * release may add a table.
121
+ * Build the grants for the application role: USAGE on the schema, DML on the store's tables and
122
+ * EXECUTE on the API key and dashboard functions, nothing else. The role must not be able to leave
123
+ * forced RLS (`grantApplicationRole` checks; these statements do not). Rerun after every
124
+ * `applySchema()`, since a release may add a table.
104
125
  */
105
126
  export declare function createSlotlockApplicationRoleGrantsDdl(role: string): string;
106
127
  /**
@@ -108,5 +129,16 @@ export declare function createSlotlockApplicationRoleGrantsDdl(role: string): st
108
129
  * `slotlock.tenant_ref`; adapters may supply an established transaction-local setting name.
109
130
  * Every policy fails closed when the setting is absent or empty, and FORCE binds the table owner.
110
131
  */
132
+ /**
133
+ * The transaction-local setting withTenant sets for a key limited to part of its tenant (RFC 0003
134
+ * G6): the ids of the resources it reaches, as a uuid[] literal; empty for every other caller.
135
+ */
136
+ export declare const SLOTLOCK_RESOURCE_SCOPE_SETTING = "slotlock.resource_scope";
137
+ /**
138
+ * The tables a key limited to part of its tenant is held to, and how each row names its resource:
139
+ * the resource itself, or the event it belongs to. Tombstones and archives name none and stay as the
140
+ * tenant policy leaves them.
141
+ */
142
+ export declare const SLOTLOCK_RESOURCE_SCOPED_TABLES: Readonly<Record<string, string>>;
111
143
  export declare function createSlotlockTenantRlsDdl(tenantContextSetting?: string): string;
112
144
  export declare const SLOTLOCK_TENANT_RLS_DDL: string;