slotlock 0.2.0 → 0.5.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.
- package/CHANGELOG.md +582 -0
- package/CONTRIBUTING.md +35 -8
- package/GOVERNANCE.md +4 -2
- package/MAINTAINERS.md +3 -2
- package/NOTICE +4 -4
- package/README.md +498 -65
- package/SECURITY.md +31 -2
- package/SPEC.md +142 -15
- package/agent-server.d.ts +62 -10
- package/agent-server.js +577 -105
- package/agent-store-backend.d.ts +12 -0
- package/agent-store-backend.js +1115 -55
- package/api-keys.d.ts +11 -3
- package/api-keys.js +29 -6
- package/application-api.d.ts +35 -1
- package/application-api.js +683 -12
- package/booking-rules.d.ts +84 -0
- package/booking-rules.js +149 -0
- package/config.d.ts +112 -0
- package/config.js +225 -0
- package/dashboard.d.ts +67 -5
- package/dashboard.js +1012 -140
- package/ddl.d.ts +45 -3
- package/ddl.js +1124 -13
- package/engine.d.ts +5 -0
- package/engine.js +23 -6
- package/event-feed.d.ts +178 -0
- package/event-feed.js +435 -0
- package/event-schema.d.ts +59 -0
- package/event-schema.js +85 -0
- package/ical-worker-thread.js +4 -2
- package/ical-worker.d.ts +8 -5
- package/ical-worker.js +9 -2
- package/index.d.ts +12 -6
- package/index.js +9 -4
- package/interop.d.ts +117 -0
- package/interop.js +356 -0
- package/maintenance.d.ts +27 -5
- package/maintenance.js +92 -28
- package/mcp-app.d.ts +7 -1
- package/mcp-app.js +259 -40
- package/metrics.d.ts +24 -0
- package/metrics.js +167 -0
- package/node-server.d.ts +9 -1
- package/node-server.js +7 -2
- package/openapi.json +10970 -0
- package/package.json +3 -2
- package/rate-limit.d.ts +80 -0
- package/rate-limit.js +741 -0
- package/rest-api.d.ts +22 -0
- package/rest-api.js +166 -11
- package/rules.js +6 -3
- package/self-host.d.ts +45 -8
- package/self-host.js +616 -46
- package/slotlock-manifest.schema.json +7 -1
- package/slotlock.manifest.json +8 -2
- package/store.d.ts +647 -28
- package/store.js +2982 -327
- package/sync.d.ts +43 -2
- package/sync.js +1515 -323
- package/timezone.d.ts +58 -3
- package/timezone.js +249 -20
- package/types.d.ts +300 -9
- package/types.js +0 -2
- package/webhooks.d.ts +91 -0
- package/webhooks.js +300 -0
package/dashboard.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { SlotlockApiKeyStore } from './api-keys.js';
|
|
2
|
-
import
|
|
3
|
-
import type
|
|
2
|
+
import { type SlotlockBookingRules } from './booking-rules.js';
|
|
3
|
+
import { type CreateWebhookEndpointResult, type SlotlockChange, type SlotlockWebhookEndpoint } from './event-feed.js';
|
|
4
|
+
import type { SlotlockSql, SlotlockStore, SlotlockWaitlistEntry } from './store.js';
|
|
5
|
+
import type { Interval, SlotlockAgendaEntry, SlotlockResource, WeeklyAvailabilityRule } from './types.js';
|
|
4
6
|
/** Resources one dashboard tenant may hold. */
|
|
5
7
|
export declare const SLOTLOCK_DASHBOARD_MAX_RESOURCES = 100;
|
|
6
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* A tenant's calendar resources, as the dashboard lists and adds them. Each write takes, last, the
|
|
10
|
+
* person who made it (`github:<user id>`) as `actor`, to record on the event feed.
|
|
11
|
+
*/
|
|
7
12
|
export interface SlotlockDashboardResources {
|
|
8
13
|
list(tenantRef: string): Promise<SlotlockResource[]>;
|
|
9
14
|
/**
|
|
@@ -11,7 +16,7 @@ export interface SlotlockDashboardResources {
|
|
|
11
16
|
* (an error with `code: 'resource_limit_reached'`) once the tenant has
|
|
12
17
|
* SLOTLOCK_DASHBOARD_MAX_RESOURCES, however many adds race, on however many servers.
|
|
13
18
|
*/
|
|
14
|
-
add(tenantRef: string, externalRef: string, timezone: string): Promise<SlotlockResource>;
|
|
19
|
+
add(tenantRef: string, externalRef: string, timezone: string, actor?: string): Promise<SlotlockResource>;
|
|
15
20
|
/**
|
|
16
21
|
* Set the bookable hours of one of the tenant's resources (`{ id }`) or of all of them; `null`
|
|
17
22
|
* hands them back to the server's and `[]` closes. Returns how many resources changed: 0 for an
|
|
@@ -19,7 +24,32 @@ export interface SlotlockDashboardResources {
|
|
|
19
24
|
*/
|
|
20
25
|
setHours(tenantRef: string, target: {
|
|
21
26
|
id: string;
|
|
22
|
-
} | 'all', rules: WeeklyAvailabilityRule[] | null): Promise<number>;
|
|
27
|
+
} | 'all', rules: WeeklyAvailabilityRule[] | null, actor?: string): Promise<number>;
|
|
28
|
+
/** What occupies the tenant's resources in `window`, by start: the overview's agenda. */
|
|
29
|
+
agenda?(tenantRef: string, window: Interval, limit: number): Promise<SlotlockAgendaEntry[]>;
|
|
30
|
+
/** The tenant's latest changes, newest first: the overview's activity. */
|
|
31
|
+
recentChanges?(tenantRef: string, limit: number): Promise<SlotlockChange[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Set the booking rules of one of the tenant's resources (null clears them): the resource, or
|
|
34
|
+
* null when it is not the tenant's. Invalid rules throw with `code: 'invalid_booking_rules'`.
|
|
35
|
+
*/
|
|
36
|
+
setRules?(tenantRef: string, id: string, rules: SlotlockBookingRules | null, actor?: string): Promise<SlotlockResource | null>;
|
|
37
|
+
/** Put one of the tenant's resources in a pool, or none: as setRules; `code: 'invalid_pool'`. */
|
|
38
|
+
setPool?(tenantRef: string, id: string, pool: string | null, actor?: string): Promise<SlotlockResource | null>;
|
|
39
|
+
/** The tenant's waitlist, oldest first, and leaving it (false when the entry is not the tenant's). */
|
|
40
|
+
waitlist?: {
|
|
41
|
+
list(tenantRef: string, limit: number): Promise<SlotlockWaitlistEntry[]>;
|
|
42
|
+
leave(tenantRef: string, id: string, actor?: string): Promise<boolean>;
|
|
43
|
+
};
|
|
44
|
+
/** The tenant's webhook endpoints, as the event feed keeps them. */
|
|
45
|
+
webhooks?: {
|
|
46
|
+
list(tenantRef: string): Promise<SlotlockWebhookEndpoint[]>;
|
|
47
|
+
create(tenantRef: string, url: string, eventTypes: readonly string[] | undefined, actor?: string): Promise<CreateWebhookEndpointResult>;
|
|
48
|
+
remove(tenantRef: string, id: string, actor?: string): Promise<boolean>;
|
|
49
|
+
enable(tenantRef: string, id: string, actor?: string): Promise<SlotlockWebhookEndpoint | null | {
|
|
50
|
+
code: 'changes_pruned';
|
|
51
|
+
}>;
|
|
52
|
+
};
|
|
23
53
|
}
|
|
24
54
|
/**
|
|
25
55
|
* What the dashboard records so a sign-in callback works once, a sent form runs once and a
|
|
@@ -47,6 +77,8 @@ export interface SlotlockDashboardState {
|
|
|
47
77
|
export interface SlotlockDashboardOptions {
|
|
48
78
|
/** Where people reach the server; the dashboard lives at `<publicUrl>/dashboard`. */
|
|
49
79
|
publicUrl: string;
|
|
80
|
+
/** What the deployment is called in the dashboard: 1-60 characters. Defaults to `Slotlock`. */
|
|
81
|
+
name?: string;
|
|
50
82
|
/**
|
|
51
83
|
* Where agents reach the server's MCP and A2A endpoints, which the dashboard shows, when it is
|
|
52
84
|
* served from another origin (on Cloudflare Workers, with the server elsewhere). Defaults to
|
|
@@ -63,11 +95,23 @@ export interface SlotlockDashboardOptions {
|
|
|
63
95
|
authorizeUrl?: string;
|
|
64
96
|
tokenUrl?: string;
|
|
65
97
|
userUrl?: string;
|
|
98
|
+
membershipsUrl?: string;
|
|
66
99
|
};
|
|
67
100
|
/** Seals sessions and sign-in state and derives CSRF tokens: 32+ random characters. */
|
|
68
101
|
sessionSecret: string;
|
|
69
102
|
/** GitHub user ids (numbers, as strings) that may sign in, or `'*'` for every GitHub account. */
|
|
70
103
|
allowedUsers: '*' | readonly string[];
|
|
104
|
+
/**
|
|
105
|
+
* GitHub organization ids (numbers, as strings) this dashboard serves. With them, a tenant is an
|
|
106
|
+
* organization (`github-org:<id>`), not a person: sign-in asks for `read:org`, and a person signs
|
|
107
|
+
* in to the served organizations they are an active member of, sharing each one's keys and
|
|
108
|
+
* resources with its other members: owners and members, not billing managers, from the first
|
|
109
|
+
* 100 memberships GitHub lists, up to 20 served organizations. Membership is read at each sign-in; leaving an organization
|
|
110
|
+
* ends access at the next sign-in, at most a session (12 hours) later, and removing an
|
|
111
|
+
* organization from this list signs its sessions out at once. Without it, each person is their
|
|
112
|
+
* own tenant (`github:<id>`).
|
|
113
|
+
*/
|
|
114
|
+
organizations?: readonly string[];
|
|
71
115
|
keys: SlotlockApiKeyStore;
|
|
72
116
|
resources: SlotlockDashboardResources;
|
|
73
117
|
/** Shared by every server behind this origin: see SlotlockDashboardState. */
|
|
@@ -76,6 +120,12 @@ export interface SlotlockDashboardOptions {
|
|
|
76
120
|
availability?: readonly WeeklyAvailabilityRule[];
|
|
77
121
|
fetch?: typeof fetch;
|
|
78
122
|
now?: () => number;
|
|
123
|
+
/**
|
|
124
|
+
* The address a request came from, as the server counts its clients (the socket's, or a trusted
|
|
125
|
+
* proxy's field such as CF-Connecting-IP), so one client's sign-ins in flight are capped below
|
|
126
|
+
* every client's. Without it, or when it returns undefined, only the cap on every client applies.
|
|
127
|
+
*/
|
|
128
|
+
clientAddress?: (request: Request) => string | undefined;
|
|
79
129
|
/**
|
|
80
130
|
* Called with whatever a request handler throws; the person sees a generic error page. Not
|
|
81
131
|
* awaited; what it throws, or its promise rejects with, is ignored.
|
|
@@ -92,6 +142,18 @@ export interface SlotlockDashboard {
|
|
|
92
142
|
* in the database (a READ COMMITTED transaction, under a per-tenant lock).
|
|
93
143
|
*/
|
|
94
144
|
export declare function createSlotlockDashboardResources(store: SlotlockStore): SlotlockDashboardResources;
|
|
145
|
+
/**
|
|
146
|
+
* Records accepted write confirmations (`SlotlockAgentConfirmationOptions.consumeAcceptance`) in
|
|
147
|
+
* Postgres, shared by every server on the database: true the first time a confirmation's nonce is
|
|
148
|
+
* recorded, false while it stays recorded, so an accepted confirmation runs its write once on any
|
|
149
|
+
* server. Kept until the confirmation's own expiry, through the same function and table as the
|
|
150
|
+
* dashboard's records (only a SHA-256 digest of the nonce is stored); pass a client, not a
|
|
151
|
+
* transaction.
|
|
152
|
+
*/
|
|
153
|
+
export declare function createSlotlockAcceptanceRecords(sql: SlotlockSql): (acceptance: {
|
|
154
|
+
nonce: string;
|
|
155
|
+
expiresAt: Date;
|
|
156
|
+
}) => Promise<boolean>;
|
|
95
157
|
/**
|
|
96
158
|
* The dashboard's records in Postgres, shared by every server on the database. Run `applySchema()`
|
|
97
159
|
* and `grantApplicationRole()` first: the serving role reaches the records only through
|