@mulmoclaude/core 3.10.0 → 3.12.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/dist/collection/registry/server/index.cjs +1 -1
- package/dist/collection/registry/server/index.js +1 -1
- package/dist/collection/server/index.cjs +2 -1
- package/dist/collection/server/index.d.ts +1 -1
- package/dist/collection/server/index.js +2 -2
- package/dist/collection/server/publishChecks.d.ts +29 -0
- package/dist/collection/server/publishManifest.d.ts +35 -3
- package/dist/collection-watchers/index.cjs +1 -1
- package/dist/collection-watchers/index.js +1 -1
- package/dist/feeds/server/index.cjs +1 -1
- package/dist/feeds/server/index.js +1 -1
- package/dist/{server-CgkkWWBd.cjs → server-BIKy55wo.cjs} +213 -8
- package/dist/server-BIKy55wo.cjs.map +1 -0
- package/dist/{server-BNe8XMtu.js → server-DkT40KgR.js} +208 -9
- package/dist/server-DkT40KgR.js.map +1 -0
- package/package.json +1 -1
- package/dist/server-BNe8XMtu.js.map +0 -1
- package/dist/server-CgkkWWBd.cjs.map +0 -1
|
@@ -19,13 +19,30 @@ var NameZ = z.string().refine(isValidCollectionName, { message: "is not a valid
|
|
|
19
19
|
* the rules compare it to `request.auth.token.email` verbatim, so any
|
|
20
20
|
* narrowing here would refuse addresses Firebase itself accepts. */
|
|
21
21
|
var EmailZ = z.string().trim().min(3).includes("@");
|
|
22
|
-
/** The
|
|
23
|
-
*
|
|
22
|
+
/** The roles the deployed rules understand.
|
|
23
|
+
*
|
|
24
|
+
* Two of them are row-scoped, in opposite directions, and the pair is what
|
|
25
|
+
* the four-way split could not express:
|
|
26
|
+
*
|
|
27
|
+
* `participant` — the layer that is NAMED but reads only its OWN rows (the
|
|
28
|
+
* rows it submitted). See `readerOf` vs `listedIn`.
|
|
29
|
+
*
|
|
30
|
+
* `assignee` — reads EVERY row and writes only the rows ASSIGNED to it. The
|
|
31
|
+
* stylist who approves their own bookings and not a colleague's; the marker
|
|
32
|
+
* who grades their own students. Which rows are theirs is
|
|
33
|
+
* `collections[cid].assigneeField`, a field on the record holding the
|
|
34
|
+
* member's address. Reads are deliberately unscoped: a stylist needs the
|
|
35
|
+
* whole day's schedule, and scoping the read makes the app unusable.
|
|
36
|
+
*
|
|
37
|
+
* The names are permanent. The deployed rules compare these strings directly
|
|
38
|
+
* and they are written into `app.json` files people commit, so a rename is a
|
|
39
|
+
* migration over published apps rather than an edit. */
|
|
24
40
|
var APP_ROLES = [
|
|
25
41
|
"owner",
|
|
26
42
|
"editor",
|
|
27
43
|
"viewer",
|
|
28
|
-
"participant"
|
|
44
|
+
"participant",
|
|
45
|
+
"assignee"
|
|
29
46
|
];
|
|
30
47
|
var RoleZ = z.enum(APP_ROLES);
|
|
31
48
|
/** `{ email: { "*" | cid: role } }`. The `"*"` key is the app-wide role; a
|
|
@@ -51,6 +68,21 @@ var CollectionConfigZ = z.object({
|
|
|
51
68
|
transitions: z.record(z.string().trim().min(1), z.array(z.string().trim().min(1))).optional(),
|
|
52
69
|
immutable: z.boolean().optional(),
|
|
53
70
|
submitOnly: z.boolean().optional(),
|
|
71
|
+
/** The field naming the member a row belongs to, for the `assignee` role.
|
|
72
|
+
*
|
|
73
|
+
* Holds an ADDRESS, because that is the only thing the rules can compare
|
|
74
|
+
* a member against (`request.auth.token.email`). A `ref` to a staff
|
|
75
|
+
* collection stores the target's primary-key slug, not an address, so it
|
|
76
|
+
* cannot be this field — declare a plain field beside the ref and let the
|
|
77
|
+
* ref stay the thing the UI renders. The alternative, having the rules
|
|
78
|
+
* `get()` the staff record to read an address off it, costs a document
|
|
79
|
+
* access on every write and puts a second document between an
|
|
80
|
+
* authorization decision and its answer.
|
|
81
|
+
*
|
|
82
|
+
* Only meaningful with a member holding `assignee` on this cid; a
|
|
83
|
+
* declaration with the role and no field is refused (`assigneeProblems`),
|
|
84
|
+
* because that member would silently hold nothing. */
|
|
85
|
+
assigneeField: z.string().trim().min(1).optional(),
|
|
54
86
|
peerVisibility: z.enum(["public", "hidden"]).optional(),
|
|
55
87
|
revealGated: z.boolean().optional(),
|
|
56
88
|
gatedFrom: NameZ.optional(),
|
|
@@ -69,9 +101,32 @@ var CollectionConfigZ = z.object({
|
|
|
69
101
|
* the rules do not coerce strings, so an ISO string reaching Firestore is a
|
|
70
102
|
* type error that fails CLOSED (`inWindow` refuses every submission and the
|
|
71
103
|
* author sees "nobody can submit", not an error). */
|
|
104
|
+
/** A window bound that lives on ANOTHER record, read at write time.
|
|
105
|
+
*
|
|
106
|
+
* `window.from` is one absolute instant for the whole collection, which is
|
|
107
|
+
* enough for a survey and useless for anything recurring: "each class opens
|
|
108
|
+
* three days before it starts, at 08:00" is a bound PER RECORD. So the bound
|
|
109
|
+
* is not computed in the rules — they have no usable date arithmetic and
|
|
110
|
+
* `request.time` is UTC, which is the wrong answer for "08:00" — it is
|
|
111
|
+
* computed by whoever schedules the class, stored on the class record as
|
|
112
|
+
* epoch millis, and merely COMPARED here.
|
|
113
|
+
*
|
|
114
|
+
* `ref` is the field on the record being written that names the target
|
|
115
|
+
* (`classId`); `collection` is the cid the target lives in, fixed in the
|
|
116
|
+
* declaration so that a path is never built out of a value a submitter wrote;
|
|
117
|
+
* `field` is the epoch-millis field on the target.
|
|
118
|
+
*
|
|
119
|
+
* Not spelled `in` — that is an operator in the rules language, and
|
|
120
|
+
* `w.fromField.in` does not parse there. */
|
|
121
|
+
var WindowRefZ = z.object({
|
|
122
|
+
ref: z.string().trim().min(1),
|
|
123
|
+
collection: NameZ,
|
|
124
|
+
field: z.string().trim().min(1)
|
|
125
|
+
}).strict();
|
|
72
126
|
var WindowZ = z.object({
|
|
73
127
|
from: z.iso.datetime().optional(),
|
|
74
|
-
until: z.iso.datetime().optional()
|
|
128
|
+
until: z.iso.datetime().optional(),
|
|
129
|
+
fromField: WindowRefZ.optional()
|
|
75
130
|
}).strict();
|
|
76
131
|
var ValidateZ = z.object({
|
|
77
132
|
required: z.array(z.string().trim().min(1)).optional(),
|
|
@@ -104,6 +159,19 @@ var SubmitZ = z.object({
|
|
|
104
159
|
idField: z.string().trim().min(1).optional(),
|
|
105
160
|
validate: ValidateZ.optional(),
|
|
106
161
|
window: WindowZ.optional(),
|
|
162
|
+
/** A field the rules PIN to the server clock on create: the record must
|
|
163
|
+
* carry `request.time` in it, and may never change it afterwards.
|
|
164
|
+
*
|
|
165
|
+
* What it buys is an order nobody can jump. A first-come app takes its
|
|
166
|
+
* capacity from rank rather than from a count — the rules cannot count
|
|
167
|
+
* documents, so "the first 8" can only ever be a reading of the rows —
|
|
168
|
+
* and a rank is only as honest as the timestamp it sorts by. `idFrom`
|
|
169
|
+
* stops a person holding two places; nothing else stops them writing
|
|
170
|
+
* yesterday's date into the field that decides who got there first.
|
|
171
|
+
*
|
|
172
|
+
* Binds EVERY create, the writer branch included, so a staff-entered row
|
|
173
|
+
* cannot be back-dated into the queue either. */
|
|
174
|
+
stampField: z.string().trim().min(1).optional(),
|
|
107
175
|
/** Per CURRENT STATUS, never a flat list: a flat list lets a customer move
|
|
108
176
|
* an approved booking's `startAt` without anyone re-approving it. */
|
|
109
177
|
selfUpdate: z.record(z.string().trim().min(1), z.array(z.string().trim().min(1))).optional(),
|
|
@@ -122,6 +190,34 @@ var PublicZ = z.object({
|
|
|
122
190
|
read: z.array(NameZ).optional(),
|
|
123
191
|
submit: z.record(NameZ, SubmitZ).optional()
|
|
124
192
|
}).strict();
|
|
193
|
+
/** The URL name an app is handed out under: `https://<host>/{slug}`.
|
|
194
|
+
*
|
|
195
|
+
* A SEPARATE name from the `aid`, and that separation is the point (design
|
|
196
|
+
* D2b). `apps/{aid}` is a shelf every user of the deployment shares and the
|
|
197
|
+
* rules' `allow create` asks only that you name yourself owner — so a
|
|
198
|
+
* memorable aid is first-come-first-served, cannot be checked for
|
|
199
|
+
* availability, and frees up again when an app is deleted. The aid is
|
|
200
|
+
* therefore a UUID, and the thing people can fight over is moved to the name
|
|
201
|
+
* that costs nothing to change.
|
|
202
|
+
*
|
|
203
|
+
* Declared here rather than kept beside `app.json` because a RESERVATION has
|
|
204
|
+
* to travel with the repository: `appSlugs/{slug}` is unreadable until the app
|
|
205
|
+
* is published (`allow read: if resource.data.published == true`), so nothing
|
|
206
|
+
* can recover which slug an app holds by asking Firestore. A second file to
|
|
207
|
+
* keep in step with the declaration is the alternative, and it is the kind of
|
|
208
|
+
* pair that goes out of step silently.
|
|
209
|
+
*
|
|
210
|
+
* The shape is stricter than `NameZ` on purpose: it is BOTH a URL path
|
|
211
|
+
* segment people read aloud and a Firestore document id. Lowercase
|
|
212
|
+
* alphanumerics separated by single hyphens covers both without a case rule
|
|
213
|
+
* that would make two slugs collide in one place and not the other.
|
|
214
|
+
*
|
|
215
|
+
* Which slug an app ended up with is the HOST's business — a wanted slug can
|
|
216
|
+
* be taken, and the host writes the one it reserved back here. Nothing in this
|
|
217
|
+
* package reads the key; it is declared so that writing it back does not make
|
|
218
|
+
* the file unparseable. */
|
|
219
|
+
var SLUG_SHAPE = "must be lowercase letters, digits and single hyphens, and must not start or end with one (e.g. sakura-hair)";
|
|
220
|
+
var SlugZ = z.string().trim().max(64).regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$/, SLUG_SHAPE).refine((slug) => !slug.includes("--"), SLUG_SHAPE);
|
|
125
221
|
/** The whole authored declaration.
|
|
126
222
|
*
|
|
127
223
|
* `owner` is accepted but is NOT the published value — publish stamps the
|
|
@@ -133,6 +229,8 @@ var PublicZ = z.object({
|
|
|
133
229
|
var AuthoredAppZ = z.object({
|
|
134
230
|
aid: NameZ,
|
|
135
231
|
name: z.string().trim().min(1).optional(),
|
|
232
|
+
/** The wanted (or reserved) URL name — see {@link SlugZ}. */
|
|
233
|
+
slug: SlugZ.optional(),
|
|
136
234
|
/** Per-worktree app id (design D6, implementation order 7). Accepted so a
|
|
137
235
|
* repository already carrying it parses; nothing reads it yet. */
|
|
138
236
|
aidEnv: z.string().trim().min(1).optional(),
|
|
@@ -194,7 +292,11 @@ function windowMillis(window) {
|
|
|
194
292
|
if (window.from !== void 0) out.fromMs = Date.parse(window.from);
|
|
195
293
|
if (window.until !== void 0) out.untilMs = Date.parse(window.until);
|
|
196
294
|
if (Object.values(out).some((value) => !Number.isFinite(value))) throw new Error(`publish: window bound is not a parseable timestamp (${JSON.stringify(window)})`);
|
|
197
|
-
|
|
295
|
+
const projected = {
|
|
296
|
+
...out,
|
|
297
|
+
...window.fromField === void 0 ? {} : { fromField: window.fromField }
|
|
298
|
+
};
|
|
299
|
+
return Object.keys(projected).length > 0 ? projected : void 0;
|
|
198
300
|
}
|
|
199
301
|
/** One `public.submit[cid]`, with its window lowered. Everything else passes
|
|
200
302
|
* through: the rules read these keys by the names the author wrote. */
|
|
@@ -621,7 +723,8 @@ function unknownCidProblems(app, collections) {
|
|
|
621
723
|
["collections", Object.keys(app.collections ?? {})],
|
|
622
724
|
["public.read", app.public?.read ?? []],
|
|
623
725
|
["public.submit", Object.keys(app.public?.submit ?? {})],
|
|
624
|
-
["participantRead", app.participantRead ?? []]
|
|
726
|
+
["participantRead", app.participantRead ?? []],
|
|
727
|
+
["members", [...new Set(Object.values(app.members).flatMap((roles) => Object.keys(roles)))].filter((key) => key !== "*")]
|
|
625
728
|
].flatMap(([where, cids]) => cids.filter((cid) => !known.has(cid)).map((cid) => `${where} names '${cid}', which is not a shared collection in this repository. Shared collections here: ${known.size > 0 ? [...known].sort().join(", ") : "(none - a schema needs storage.type \"firestore\")"}.`));
|
|
626
729
|
}
|
|
627
730
|
/** Everything publish refuses, as lines the author can act on.
|
|
@@ -638,7 +741,10 @@ function publishProblems(app, collections, publisherEmail) {
|
|
|
638
741
|
...mailProblems(app),
|
|
639
742
|
...submitShapeProblems(app),
|
|
640
743
|
...coherenceProblems(app),
|
|
641
|
-
...primaryKeyProblems(app, collections)
|
|
744
|
+
...primaryKeyProblems(app, collections),
|
|
745
|
+
...assigneeProblems(app),
|
|
746
|
+
...stampProblems(app),
|
|
747
|
+
...windowRefProblems(app, collections)
|
|
642
748
|
];
|
|
643
749
|
}
|
|
644
750
|
/** A public submission must NOT be allowed to name its own primary key.
|
|
@@ -668,6 +774,99 @@ function primaryKeyProblems(app, collections) {
|
|
|
668
774
|
return [`public.submit.${cid}.createFields must NOT include "${primaryKey}", the schema's primaryKey: the rules can pin the document id but not the value of a field, so a submitter could write at their own id while claiming another record's. A shared record's identity is its document id — the store fills the field from it, and a submitted value is either the same thing or a lie that is thrown away.`];
|
|
669
775
|
});
|
|
670
776
|
}
|
|
777
|
+
/** `assignee` without the field that says which rows are theirs.
|
|
778
|
+
*
|
|
779
|
+
* A FAIL-CLOSED trap of the worst kind, because it fails closed for one
|
|
780
|
+
* person and nobody else: the rules ask `collections[cid].assigneeField` for
|
|
781
|
+
* the field to compare, find nothing, and refuse every write that member
|
|
782
|
+
* makes. The app works for the owner who set it up, and the member it was set
|
|
783
|
+
* up for is told only "permission denied".
|
|
784
|
+
*
|
|
785
|
+
* `'*': "assignee"` is refused outright rather than checked against every
|
|
786
|
+
* collection. The role means "the rows assigned to you", and what counts as
|
|
787
|
+
* assigned is per collection — an app-wide one would need the same field name
|
|
788
|
+
* to be right everywhere, and where it is missing it silently means "no
|
|
789
|
+
* access to this collection" rather than "no scoping here".
|
|
790
|
+
*/
|
|
791
|
+
function assigneeProblems(app) {
|
|
792
|
+
return Object.entries(app.members).flatMap(([email, roles]) => Object.entries(roles).flatMap(([cid, role]) => {
|
|
793
|
+
if (role !== "assignee") return [];
|
|
794
|
+
if (cid === "*") return [`members["${email}"] holds "assignee" under "*", and the role cannot be app-wide: which rows are yours is declared per collection (\`collections.<cid>.assigneeField\`). Name the collections instead — { "bookings": "assignee" }.`];
|
|
795
|
+
if (app.collections?.[cid]?.assigneeField !== void 0) return [];
|
|
796
|
+
return [`members["${email}"] holds "assignee" on '${cid}', but collections.${cid}.assigneeField does not say which field names the member a row belongs to. Add it (assigneeField: "<a field holding an address>"), or give a role that is not row-scoped. Without it the rules have nothing to compare and refuse every write that member makes, while the app keeps working for everybody else.`];
|
|
797
|
+
}));
|
|
798
|
+
}
|
|
799
|
+
/** A server-stamped field the submitter cannot write, or can rewrite later.
|
|
800
|
+
*
|
|
801
|
+
* Both failures are silent in opposite directions. Left out of
|
|
802
|
+
* `createFields`, the rules refuse every submission (`hasOnly(createFields)`
|
|
803
|
+
* rejects the key the stamp check requires) — an app nobody can use. Left IN
|
|
804
|
+
* a `selfUpdate` list, the field the queue is ordered by becomes editable by
|
|
805
|
+
* the person standing in the queue. */
|
|
806
|
+
function stampProblems(app) {
|
|
807
|
+
return Object.entries(app.public?.submit ?? {}).flatMap(([cid, submit]) => {
|
|
808
|
+
const stamp = submit.stampField;
|
|
809
|
+
if (stamp === void 0) return [];
|
|
810
|
+
const problems = [];
|
|
811
|
+
if (!submit.createFields.includes(stamp)) problems.push(`public.submit.${cid}.stampField names '${stamp}', which is not in createFields. The rules require the record to CARRY the server time in that field, and refuse any key outside createFields — so every submission is denied. Add it to createFields; the page fills it in, not the person.`);
|
|
812
|
+
for (const [status, fields] of Object.entries(submit.selfUpdate ?? {})) {
|
|
813
|
+
if (!fields.includes(stamp)) continue;
|
|
814
|
+
problems.push(`public.submit.${cid}.selfUpdate.${status} lets the submitter write '${stamp}', which is the field stampField pins to the server clock. Whatever that field orders — a first-come queue, an audit trail — could then be rewritten by the person it ranks. Remove it from selfUpdate.`);
|
|
815
|
+
}
|
|
816
|
+
return problems;
|
|
817
|
+
});
|
|
818
|
+
}
|
|
819
|
+
/** A per-record window bound pointing at a collection or a field the submitter
|
|
820
|
+
* never writes.
|
|
821
|
+
*
|
|
822
|
+
* `fromField` makes the rules read another record, and every part of that
|
|
823
|
+
* read is fail-closed: an unknown collection, or a `ref` the submission does
|
|
824
|
+
* not carry, means the bound can never be satisfied and the form is shut for
|
|
825
|
+
* good. */
|
|
826
|
+
function windowRefProblems(app, collections) {
|
|
827
|
+
const known = new Set(collections.map((collection) => collection.cid));
|
|
828
|
+
return Object.entries(app.public?.submit ?? {}).flatMap(([cid, submit]) => {
|
|
829
|
+
const ref = submit.window?.fromField;
|
|
830
|
+
if (ref === void 0) return [];
|
|
831
|
+
const problems = [];
|
|
832
|
+
if (!known.has(ref.collection)) problems.push(`public.submit.${cid}.window.fromField.collection names '${ref.collection}', which is not a shared collection in this repository. The rules read the opening time off a record there, so nothing can ever be submitted. Shared collections here: ${known.size > 0 ? [...known].sort().join(", ") : "(none)"}.`);
|
|
833
|
+
if (!submit.createFields.includes(ref.ref)) problems.push(`public.submit.${cid}.window.fromField.ref names '${ref.ref}', which is not in createFields. The rules take the target record's id from that field ON THE SUBMISSION — if the submitter never writes it, there is nothing to look up and every submission is refused.`);
|
|
834
|
+
return problems;
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
/** What publish will actually promote, checked as the PAIR it becomes.
|
|
838
|
+
*
|
|
839
|
+
* `publishProblems` reads the manifest, where `members` and `collections` sit
|
|
840
|
+
* side by side and agree. Publish does not write that pair. It writes the
|
|
841
|
+
* roster from the manifest and the collection configuration from what DEPLOY
|
|
842
|
+
* staged, so the app that lands is one half of each — and no check has ever
|
|
843
|
+
* looked at that combination.
|
|
844
|
+
*
|
|
845
|
+
* The sequence that gets through: deploy revision A with no `assigneeField`,
|
|
846
|
+
* add the field AND the member in revision B, publish without redeploying.
|
|
847
|
+
* Every manifest-level check passes on a declaration that is internally sound,
|
|
848
|
+
* while what lands is A's field-less configuration beside B's roster — an
|
|
849
|
+
* assignee with nothing to be compared against, refused every write, in an app
|
|
850
|
+
* that keeps working for everybody else. That is the precise trap
|
|
851
|
+
* `assigneeProblems` exists to prevent, reached by the one route it cannot
|
|
852
|
+
* see.
|
|
853
|
+
*
|
|
854
|
+
* Separate from `publishProblems` because it needs what deploy staged, which
|
|
855
|
+
* is a Firestore read the host makes and this package does not. It is checked
|
|
856
|
+
* against `stagedRuleConfig` — the same function the projection uses — rather
|
|
857
|
+
* than against a re-derivation, so the value validated is the value written.
|
|
858
|
+
*
|
|
859
|
+
* Only the staged half can be stale, so only that half is named and the fix is
|
|
860
|
+
* "deploy again" rather than "fix the declaration". */
|
|
861
|
+
function promotedRoleProblems(app, staged) {
|
|
862
|
+
const promoted = stagedRuleConfig(staged).collections ?? {};
|
|
863
|
+
const stagedCids = new Set(staged.map((entry) => entry.cid));
|
|
864
|
+
return Object.entries(app.members).flatMap(([email, roles]) => Object.entries(roles).flatMap(([cid, role]) => {
|
|
865
|
+
if (role !== "assignee" || cid === "*" || !stagedCids.has(cid)) return [];
|
|
866
|
+
if (promoted[cid]?.assigneeField !== void 0) return [];
|
|
867
|
+
return [`members["${email}"] holds "assignee" on '${cid}', and the STAGED version of '${cid}' — the one publish promotes — carries no assigneeField, even if app.json declares one now. Publish writes the roster from app.json and the collection configuration from the deploy, so that member would land with nothing to be compared against: refused every write, while the app keeps working for everybody else. Run deploy again, so the version being published is the one the declaration describes.`];
|
|
868
|
+
}));
|
|
869
|
+
}
|
|
671
870
|
//#endregion
|
|
672
871
|
//#region src/collection/server/skillAssets.ts
|
|
673
872
|
/** Read a collection's custom-view HTML, path-safely. `viewFile` is a
|
|
@@ -2738,6 +2937,6 @@ function makeManageCollectionTool(deps = {}) {
|
|
|
2738
2937
|
};
|
|
2739
2938
|
}
|
|
2740
2939
|
//#endregion
|
|
2741
|
-
export {
|
|
2940
|
+
export { AuthoredAppZ as $, runQueryOverRows as A, APPS_COLLECTION as B, STORE_UNREADABLE as C, recordFieldProblem as D, compileRecordZ as E, readCustomViewI18n as F, appSlugDoc as G, PUBLIC_CONFIG_DOC as H, readSkillTemplate as I, projectDeploy as J, appStagingPath as K, bindsSubmitterIdentity as L, buildCollectionActionSeedPrompt as M, promptPathsFor as N, runCollectionQuery as O, readCustomViewHtml as P, APP_ROLES as Q, promotedRoleProblems as R, MAX_RECORD_ISSUES as S, validateRecordObject as T, appConfigPath as U, APP_SLUGS_COLLECTION as V, appSchemasPath as W, promoteSchema as X, projectPublish as Y, stagedRuleConfig as Z, computeCollectionIcon as _, deleteCollection as a, applyMutateAction as b, computeSuccessor as c, isTriggerDue as d, parseAuthoredApp as et, maybeSpawnSuccessor as f, ONE_SECOND_MS as g, successorId as h, deleteCustomView as i, buildActionSeedPrompt as j, enrichItems as k, daysInMonth as l, resolveEvery as m, MAX_UNSELECTIVE_ITEMS as n, deleteCollectionRefusalMessage as o, parseCivil as p, projectApp as q, makeManageCollectionTool as r, advanceTriggerDate as s, MAX_SCHEMA_ISSUES as t, formatCivil as u, buildWorkspaceOntology as v, validateCollectionRecords as w, firstMutateParamProblem as x, schemaRelations as y, publishProblems as z };
|
|
2742
2941
|
|
|
2743
|
-
//# sourceMappingURL=server-
|
|
2942
|
+
//# sourceMappingURL=server-DkT40KgR.js.map
|