@objectstack/objectql 7.1.0 → 7.2.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/index.d.mts +104 -1
- package/dist/index.d.ts +104 -1
- package/dist/index.js +326 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +329 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -454,7 +454,9 @@ var SchemaRegistry = class {
|
|
|
454
454
|
const direct = collection.get(name);
|
|
455
455
|
if (direct) return direct;
|
|
456
456
|
for (const [key, item] of collection) {
|
|
457
|
-
if (key.endsWith(`:${name}`))
|
|
457
|
+
if (key.endsWith(`:${name}`)) {
|
|
458
|
+
return item;
|
|
459
|
+
}
|
|
458
460
|
}
|
|
459
461
|
return void 0;
|
|
460
462
|
}
|
|
@@ -1306,6 +1308,12 @@ import { parseFilterAST, isFilterAST } from "@objectstack/spec/data";
|
|
|
1306
1308
|
import { PLURAL_TO_SINGULAR as PLURAL_TO_SINGULAR3, SINGULAR_TO_PLURAL as SINGULAR_TO_PLURAL2 } from "@objectstack/spec/shared";
|
|
1307
1309
|
import { METADATA_FORM_REGISTRY } from "@objectstack/spec/system";
|
|
1308
1310
|
import { DEFAULT_METADATA_TYPE_REGISTRY as DEFAULT_METADATA_TYPE_REGISTRY2, getMetadataTypeSchema as getMetadataTypeSchema2 } from "@objectstack/spec/kernel";
|
|
1311
|
+
import {
|
|
1312
|
+
extractProtection,
|
|
1313
|
+
evaluateLockForWrite,
|
|
1314
|
+
evaluateLockForDelete,
|
|
1315
|
+
resolveLockState
|
|
1316
|
+
} from "@objectstack/spec/kernel";
|
|
1309
1317
|
import { z } from "zod";
|
|
1310
1318
|
|
|
1311
1319
|
// src/metadata-diagnostics.ts
|
|
@@ -1553,6 +1561,19 @@ function resolveOverlaySchema(type, _item) {
|
|
|
1553
1561
|
const singular = PLURAL_TO_SINGULAR3[type] ?? type;
|
|
1554
1562
|
return getMetadataTypeSchema2(singular) ?? null;
|
|
1555
1563
|
}
|
|
1564
|
+
function mergeArtifactProtection(item, artifactItem) {
|
|
1565
|
+
if (item === void 0 || item === null) return item;
|
|
1566
|
+
if (artifactItem === void 0 || artifactItem === null) return item;
|
|
1567
|
+
const a = artifactItem;
|
|
1568
|
+
if (typeof a !== "object") return item;
|
|
1569
|
+
const out = { ...item };
|
|
1570
|
+
if (a._lock !== void 0) out._lock = a._lock;
|
|
1571
|
+
if (a._lockReason !== void 0) out._lockReason = a._lockReason;
|
|
1572
|
+
if (a._packageId !== void 0) out._packageId = a._packageId;
|
|
1573
|
+
if (a._packageVersion !== void 0) out._packageVersion = a._packageVersion;
|
|
1574
|
+
if (a._provenance !== void 0) out._provenance = a._provenance;
|
|
1575
|
+
return out;
|
|
1576
|
+
}
|
|
1556
1577
|
function simpleHash(str) {
|
|
1557
1578
|
let hash = 0;
|
|
1558
1579
|
for (let i = 0; i < str.length; i++) {
|
|
@@ -2044,6 +2065,7 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2044
2065
|
const includeWarnings = request.severity === "warning";
|
|
2045
2066
|
const targetTypes = request.type ? [request.type] : DEFAULT_METADATA_TYPE_REGISTRY2.filter((e) => getMetadataTypeSchema2(e.type)).map((e) => e.type);
|
|
2046
2067
|
const entries = [];
|
|
2068
|
+
const stats = {};
|
|
2047
2069
|
let scannedItems = 0;
|
|
2048
2070
|
for (const t of targetTypes) {
|
|
2049
2071
|
let listed;
|
|
@@ -2057,8 +2079,11 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2057
2079
|
continue;
|
|
2058
2080
|
}
|
|
2059
2081
|
const items = Array.isArray(listed?.items) ? listed.items : Array.isArray(listed) ? listed : [];
|
|
2082
|
+
const pkgSet = /* @__PURE__ */ new Set();
|
|
2060
2083
|
for (const item of items) {
|
|
2061
2084
|
scannedItems += 1;
|
|
2085
|
+
const pkg = item?._packageId ?? null;
|
|
2086
|
+
if (pkg) pkgSet.add(pkg);
|
|
2062
2087
|
const diag = item?._diagnostics ?? computeMetadataDiagnostics(t, item);
|
|
2063
2088
|
if (!diag) continue;
|
|
2064
2089
|
if (diag.valid && !includeWarnings) continue;
|
|
@@ -2069,12 +2094,14 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2069
2094
|
diagnostics: diag
|
|
2070
2095
|
});
|
|
2071
2096
|
}
|
|
2097
|
+
stats[t] = { count: items.length, packages: [...pkgSet].sort() };
|
|
2072
2098
|
}
|
|
2073
2099
|
return {
|
|
2074
2100
|
entries,
|
|
2075
2101
|
total: entries.length,
|
|
2076
2102
|
scannedTypes: targetTypes.length,
|
|
2077
|
-
scannedItems
|
|
2103
|
+
scannedItems,
|
|
2104
|
+
stats
|
|
2078
2105
|
};
|
|
2079
2106
|
}
|
|
2080
2107
|
async getMetaItems(request) {
|
|
@@ -2171,7 +2198,16 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2171
2198
|
}
|
|
2172
2199
|
return {
|
|
2173
2200
|
type: request.type,
|
|
2174
|
-
items: decorateMetadataItems(
|
|
2201
|
+
items: decorateMetadataItems(
|
|
2202
|
+
request.type,
|
|
2203
|
+
items.map((it) => {
|
|
2204
|
+
const a = this.lookupArtifactItem(
|
|
2205
|
+
request.type,
|
|
2206
|
+
it?.name
|
|
2207
|
+
);
|
|
2208
|
+
return mergeArtifactProtection(it, a);
|
|
2209
|
+
})
|
|
2210
|
+
)
|
|
2175
2211
|
};
|
|
2176
2212
|
}
|
|
2177
2213
|
async getMetaItem(request) {
|
|
@@ -2245,10 +2281,26 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2245
2281
|
if (alt) item = this.engine.registry.getItem(alt, request.name);
|
|
2246
2282
|
}
|
|
2247
2283
|
}
|
|
2284
|
+
const artifactItem = this.lookupArtifactItem(request.type, request.name);
|
|
2285
|
+
const decorated = decorateMetadataItem(
|
|
2286
|
+
request.type,
|
|
2287
|
+
mergeArtifactProtection(item, artifactItem)
|
|
2288
|
+
);
|
|
2289
|
+
const artifactBacked = this.isArtifactBacked(request.type, request.name);
|
|
2290
|
+
const lockState = resolveLockState(decorated, artifactBacked);
|
|
2248
2291
|
return {
|
|
2249
2292
|
type: request.type,
|
|
2250
2293
|
name: request.name,
|
|
2251
|
-
item:
|
|
2294
|
+
item: decorated,
|
|
2295
|
+
lock: lockState.lock,
|
|
2296
|
+
...lockState.lockReason !== void 0 ? { lockReason: lockState.lockReason } : {},
|
|
2297
|
+
...lockState.lockSource !== void 0 ? { lockSource: lockState.lockSource } : {},
|
|
2298
|
+
...lockState.provenance !== void 0 ? { provenance: lockState.provenance } : {},
|
|
2299
|
+
...lockState.packageId !== void 0 ? { packageId: lockState.packageId } : {},
|
|
2300
|
+
...lockState.packageVersion !== void 0 ? { packageVersion: lockState.packageVersion } : {},
|
|
2301
|
+
editable: lockState.editable,
|
|
2302
|
+
deletable: lockState.deletable,
|
|
2303
|
+
resettable: lockState.resettable
|
|
2252
2304
|
};
|
|
2253
2305
|
}
|
|
2254
2306
|
/**
|
|
@@ -2328,6 +2380,9 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2328
2380
|
}
|
|
2329
2381
|
const effective = overlay ?? code;
|
|
2330
2382
|
const _diagnostics = effective !== null && effective !== void 0 ? computeMetadataDiagnostics(request.type, effective) : void 0;
|
|
2383
|
+
const artifactBacked = this.isArtifactBacked(request.type, request.name);
|
|
2384
|
+
const lockSource = code ?? overlay ?? {};
|
|
2385
|
+
const lockState = resolveLockState(lockSource, artifactBacked);
|
|
2331
2386
|
return {
|
|
2332
2387
|
type: request.type,
|
|
2333
2388
|
name: request.name,
|
|
@@ -2335,9 +2390,69 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
2335
2390
|
overlay,
|
|
2336
2391
|
overlayScope,
|
|
2337
2392
|
effective,
|
|
2338
|
-
..._diagnostics ? { _diagnostics } : {}
|
|
2393
|
+
..._diagnostics ? { _diagnostics } : {},
|
|
2394
|
+
lock: lockState.lock,
|
|
2395
|
+
...lockState.lockReason !== void 0 ? { lockReason: lockState.lockReason } : {},
|
|
2396
|
+
...lockState.lockSource !== void 0 ? { lockSource: lockState.lockSource } : {},
|
|
2397
|
+
...lockState.provenance !== void 0 ? { provenance: lockState.provenance } : {},
|
|
2398
|
+
...lockState.packageId !== void 0 ? { packageId: lockState.packageId } : {},
|
|
2399
|
+
...lockState.packageVersion !== void 0 ? { packageVersion: lockState.packageVersion } : {},
|
|
2400
|
+
editable: lockState.editable,
|
|
2401
|
+
deletable: lockState.deletable,
|
|
2402
|
+
resettable: lockState.resettable
|
|
2339
2403
|
};
|
|
2340
2404
|
}
|
|
2405
|
+
/**
|
|
2406
|
+
* ADR-0010 §3.6 / Phase 4.1 — read the metadata-protection audit log
|
|
2407
|
+
* for a single item. Returns the most-recent rows of
|
|
2408
|
+
* `sys_metadata_audit` for this (type, name) tuple, sorted newest
|
|
2409
|
+
* first. Refused (`denied`) and forced (`forced`) writes both appear
|
|
2410
|
+
* here — they never reach the `history` endpoint, which only tracks
|
|
2411
|
+
* successful body snapshots.
|
|
2412
|
+
*
|
|
2413
|
+
* The table is provisioned by `platform-objects` and is the
|
|
2414
|
+
* compliance surface for the lock-enforcement story. When the
|
|
2415
|
+
* environment has not yet provisioned the table (legacy install
|
|
2416
|
+
* prior to ADR-0010) the call returns `{ events: [] }` instead of
|
|
2417
|
+
* raising, keeping the Studio tab harmless.
|
|
2418
|
+
*/
|
|
2419
|
+
async auditMetaItem(request) {
|
|
2420
|
+
const singular = PLURAL_TO_SINGULAR3[request.type] ?? request.type;
|
|
2421
|
+
const limit = Math.min(
|
|
2422
|
+
Math.max(1, request.limit ?? 100),
|
|
2423
|
+
500
|
|
2424
|
+
);
|
|
2425
|
+
try {
|
|
2426
|
+
const where = {
|
|
2427
|
+
type: singular,
|
|
2428
|
+
name: request.name
|
|
2429
|
+
};
|
|
2430
|
+
const rows = await this.engine.find("sys_metadata_audit", {
|
|
2431
|
+
where,
|
|
2432
|
+
orderBy: [{ field: "occurred_at", direction: "desc" }],
|
|
2433
|
+
limit
|
|
2434
|
+
});
|
|
2435
|
+
const events = (Array.isArray(rows) ? rows : []).map((r) => ({
|
|
2436
|
+
id: r.id,
|
|
2437
|
+
occurredAt: typeof r.occurred_at === "string" ? r.occurred_at : r.occurred_at instanceof Date ? r.occurred_at.toISOString() : String(r.occurred_at ?? ""),
|
|
2438
|
+
actor: String(r.actor ?? "system"),
|
|
2439
|
+
source: r.source ?? null,
|
|
2440
|
+
operation: r.operation,
|
|
2441
|
+
outcome: r.outcome,
|
|
2442
|
+
code: String(r.code ?? ""),
|
|
2443
|
+
lockState: r.lock_state ?? null,
|
|
2444
|
+
lockOverridden: Boolean(r.lock_overridden),
|
|
2445
|
+
requestId: r.request_id ?? null,
|
|
2446
|
+
note: r.note ?? null
|
|
2447
|
+
}));
|
|
2448
|
+
return { events };
|
|
2449
|
+
} catch (err) {
|
|
2450
|
+
console.warn(
|
|
2451
|
+
`[Protocol] auditMetaItem read failed for ${request.type}/${request.name}: ${err?.message ?? err}`
|
|
2452
|
+
);
|
|
2453
|
+
return { events: [] };
|
|
2454
|
+
}
|
|
2455
|
+
}
|
|
2341
2456
|
async getUiView(request) {
|
|
2342
2457
|
const schema = this.engine.registry.getObject(request.object);
|
|
2343
2458
|
if (!schema) throw new Error(`Object ${request.object} not found`);
|
|
@@ -3273,6 +3388,158 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3273
3388
|
if (!item || !item._packageId) return false;
|
|
3274
3389
|
return item._packageId !== "sys_metadata";
|
|
3275
3390
|
}
|
|
3391
|
+
// ───────────────────────────────────────────────────────────────────
|
|
3392
|
+
// ADR-0010 — metadata protection (Phase 1: L3 item-level lock)
|
|
3393
|
+
// ───────────────────────────────────────────────────────────────────
|
|
3394
|
+
/**
|
|
3395
|
+
* Look up an item from the artifact registry across both the requested
|
|
3396
|
+
* type and its singular/plural twin. Returns `undefined` when the
|
|
3397
|
+
* registry is unavailable or the item is not artifact-backed.
|
|
3398
|
+
*/
|
|
3399
|
+
lookupArtifactItem(type, name) {
|
|
3400
|
+
const registry = this.engine?.registry;
|
|
3401
|
+
if (!registry || typeof registry.getItem !== "function") return void 0;
|
|
3402
|
+
const singular = PLURAL_TO_SINGULAR3[type] ?? type;
|
|
3403
|
+
return registry.getItem(singular, name) ?? registry.getItem(type, name);
|
|
3404
|
+
}
|
|
3405
|
+
/**
|
|
3406
|
+
* Resolve the effective `_lock` for an item by consulting the
|
|
3407
|
+
* artifact registry first, then the persisted overlay row. Artifact
|
|
3408
|
+
* always wins — by design, an overlay cannot loosen a packaged
|
|
3409
|
+
* lock (ADR-0010 §3.3).
|
|
3410
|
+
*
|
|
3411
|
+
* Returns `'none'` when nothing is locked, which is the common
|
|
3412
|
+
* case. Safe to call when `environmentId` is undefined (control-
|
|
3413
|
+
* plane bootstrap) — the lock check is only meaningful in tenant
|
|
3414
|
+
* scope and the caller is expected to also gate on `environmentId`.
|
|
3415
|
+
*/
|
|
3416
|
+
async getEffectiveLock(type, name, organizationId) {
|
|
3417
|
+
const registry = this.engine?.registry;
|
|
3418
|
+
const singular = PLURAL_TO_SINGULAR3[type] ?? type;
|
|
3419
|
+
let artifactItem;
|
|
3420
|
+
if (registry && typeof registry.getItem === "function") {
|
|
3421
|
+
artifactItem = registry.getItem(singular, name) ?? registry.getItem(type, name);
|
|
3422
|
+
}
|
|
3423
|
+
if (artifactItem && artifactItem._packageId && artifactItem._packageId !== "sys_metadata") {
|
|
3424
|
+
const p = extractProtection(artifactItem);
|
|
3425
|
+
if (p.lock !== "none") {
|
|
3426
|
+
return { lock: p.lock, lockReason: p.lockReason, lockSource: "artifact" };
|
|
3427
|
+
}
|
|
3428
|
+
}
|
|
3429
|
+
try {
|
|
3430
|
+
const where = {
|
|
3431
|
+
type,
|
|
3432
|
+
name,
|
|
3433
|
+
state: "active",
|
|
3434
|
+
organization_id: organizationId ?? null
|
|
3435
|
+
};
|
|
3436
|
+
const row = await this.engine.findOne("sys_metadata", { where });
|
|
3437
|
+
if (row) {
|
|
3438
|
+
const body = typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata;
|
|
3439
|
+
const p = extractProtection(body);
|
|
3440
|
+
if (p.lock !== "none") {
|
|
3441
|
+
return { lock: p.lock, lockReason: p.lockReason, lockSource: "overlay" };
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
} catch {
|
|
3445
|
+
}
|
|
3446
|
+
return { lock: "none", lockReason: void 0, lockSource: void 0 };
|
|
3447
|
+
}
|
|
3448
|
+
/**
|
|
3449
|
+
* Best-effort audit-row writer (ADR-0010 §3.6). Failures here are
|
|
3450
|
+
* logged but never block the underlying decision: an environment
|
|
3451
|
+
* without the audit table provisioned (legacy installs before this
|
|
3452
|
+
* ADR landed) still answers normal API calls, just without the
|
|
3453
|
+
* compliance trail. Phase 2 will make the audit table a hard
|
|
3454
|
+
* dependency.
|
|
3455
|
+
*/
|
|
3456
|
+
async recordMetadataAudit(entry) {
|
|
3457
|
+
try {
|
|
3458
|
+
await this.engine.insert("sys_metadata_audit", {
|
|
3459
|
+
occurred_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3460
|
+
actor: entry.actor ?? "system",
|
|
3461
|
+
source: entry.source ?? "protocol",
|
|
3462
|
+
type: PLURAL_TO_SINGULAR3[entry.type] ?? entry.type,
|
|
3463
|
+
name: entry.name,
|
|
3464
|
+
organization_id: entry.organizationId ?? null,
|
|
3465
|
+
operation: entry.operation,
|
|
3466
|
+
outcome: entry.outcome,
|
|
3467
|
+
code: entry.code,
|
|
3468
|
+
lock_state: entry.lockState ?? "none",
|
|
3469
|
+
lock_overridden: entry.lockOverridden ?? false,
|
|
3470
|
+
request_id: entry.requestId ?? null,
|
|
3471
|
+
note: entry.note ?? null
|
|
3472
|
+
});
|
|
3473
|
+
} catch (err) {
|
|
3474
|
+
console.warn(
|
|
3475
|
+
`[Protocol] sys_metadata_audit write failed for ${entry.type}/${entry.name}: ${err?.message ?? err}`
|
|
3476
|
+
);
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
/**
|
|
3480
|
+
* Phase 1 L3 enforcement for write operations (save / publish /
|
|
3481
|
+
* rollback). Returns null on allow. Returns the structured `Error`
|
|
3482
|
+
* the caller should `throw` on deny — also records the denial in
|
|
3483
|
+
* the audit log so refused attempts are visible in compliance
|
|
3484
|
+
* reports (refused writes never reach sys_metadata_history).
|
|
3485
|
+
*/
|
|
3486
|
+
async assertLockAllowsWrite(args) {
|
|
3487
|
+
if (this.environmentId === void 0) return null;
|
|
3488
|
+
const state = await this.getEffectiveLock(args.type, args.name, args.organizationId ?? null);
|
|
3489
|
+
const refusal = evaluateLockForWrite(state.lock);
|
|
3490
|
+
if (!refusal) return null;
|
|
3491
|
+
const reason = state.lockReason ?? refusal.reason;
|
|
3492
|
+
const err = new Error(
|
|
3493
|
+
`[item_locked] ${args.type}/${args.name} is locked (_lock=${state.lock}${state.lockSource ? `, source=${state.lockSource}` : ""}). ${reason} \u2014 See ADR-0010 \xA73.3.`
|
|
3494
|
+
);
|
|
3495
|
+
err.code = "item_locked";
|
|
3496
|
+
err.status = 403;
|
|
3497
|
+
err.lock = state.lock;
|
|
3498
|
+
err.lockReason = reason;
|
|
3499
|
+
await this.recordMetadataAudit({
|
|
3500
|
+
type: args.type,
|
|
3501
|
+
name: args.name,
|
|
3502
|
+
organizationId: args.organizationId ?? null,
|
|
3503
|
+
operation: args.operation,
|
|
3504
|
+
outcome: "denied",
|
|
3505
|
+
code: "item_locked",
|
|
3506
|
+
lockState: state.lock,
|
|
3507
|
+
actor: args.actor,
|
|
3508
|
+
source: args.source ?? `protocol.${args.operation}MetaItem`,
|
|
3509
|
+
requestId: args.requestId,
|
|
3510
|
+
note: reason
|
|
3511
|
+
});
|
|
3512
|
+
return err;
|
|
3513
|
+
}
|
|
3514
|
+
/** Counterpart of {@link assertLockAllowsWrite} for delete. */
|
|
3515
|
+
async assertLockAllowsDelete(args) {
|
|
3516
|
+
if (this.environmentId === void 0) return null;
|
|
3517
|
+
const state = await this.getEffectiveLock(args.type, args.name, args.organizationId ?? null);
|
|
3518
|
+
const refusal = evaluateLockForDelete(state.lock);
|
|
3519
|
+
if (!refusal) return null;
|
|
3520
|
+
const reason = state.lockReason ?? refusal.reason;
|
|
3521
|
+
const err = new Error(
|
|
3522
|
+
`[item_locked] ${args.type}/${args.name} is locked (_lock=${state.lock}${state.lockSource ? `, source=${state.lockSource}` : ""}). ${reason} \u2014 See ADR-0010 \xA73.3.`
|
|
3523
|
+
);
|
|
3524
|
+
err.code = "item_locked";
|
|
3525
|
+
err.status = 403;
|
|
3526
|
+
err.lock = state.lock;
|
|
3527
|
+
err.lockReason = reason;
|
|
3528
|
+
await this.recordMetadataAudit({
|
|
3529
|
+
type: args.type,
|
|
3530
|
+
name: args.name,
|
|
3531
|
+
organizationId: args.organizationId ?? null,
|
|
3532
|
+
operation: "delete",
|
|
3533
|
+
outcome: "denied",
|
|
3534
|
+
code: "item_locked",
|
|
3535
|
+
lockState: state.lock,
|
|
3536
|
+
actor: args.actor,
|
|
3537
|
+
source: args.source ?? "protocol.deleteMetaItem",
|
|
3538
|
+
requestId: args.requestId,
|
|
3539
|
+
note: reason
|
|
3540
|
+
});
|
|
3541
|
+
return err;
|
|
3542
|
+
}
|
|
3276
3543
|
/**
|
|
3277
3544
|
* Mirror an object-type overlay write into the in-memory engine
|
|
3278
3545
|
* registry so subsequent CRUD finds the new schema. Idempotent and
|
|
@@ -3319,6 +3586,15 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3319
3586
|
err.status = 403;
|
|
3320
3587
|
throw err;
|
|
3321
3588
|
}
|
|
3589
|
+
const lockErr = await this.assertLockAllowsWrite({
|
|
3590
|
+
type: request.type,
|
|
3591
|
+
name: request.name,
|
|
3592
|
+
...request.organizationId ? { organizationId: request.organizationId } : {},
|
|
3593
|
+
operation: "save",
|
|
3594
|
+
...request.actor ? { actor: request.actor } : {},
|
|
3595
|
+
source: "protocol.saveMetaItem"
|
|
3596
|
+
});
|
|
3597
|
+
if (lockErr) throw lockErr;
|
|
3322
3598
|
}
|
|
3323
3599
|
const singularType = PLURAL_TO_SINGULAR3[request.type] ?? request.type;
|
|
3324
3600
|
if (!request.force && (singularType === "object" || singularType === "field")) {
|
|
@@ -3400,6 +3676,17 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3400
3676
|
if (mode === "publish") {
|
|
3401
3677
|
this.applyObjectRegistryMutation(request);
|
|
3402
3678
|
}
|
|
3679
|
+
await this.recordMetadataAudit({
|
|
3680
|
+
type: request.type,
|
|
3681
|
+
name: request.name,
|
|
3682
|
+
organizationId: orgId,
|
|
3683
|
+
operation: "save",
|
|
3684
|
+
outcome: "allowed",
|
|
3685
|
+
code: "ok",
|
|
3686
|
+
...request.actor ? { actor: request.actor } : {},
|
|
3687
|
+
source: "protocol.saveMetaItem",
|
|
3688
|
+
note: mode === "draft" ? "draft" : "active"
|
|
3689
|
+
});
|
|
3403
3690
|
return {
|
|
3404
3691
|
success: true,
|
|
3405
3692
|
version: result.version,
|
|
@@ -3522,6 +3809,15 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3522
3809
|
err.status = 403;
|
|
3523
3810
|
throw err;
|
|
3524
3811
|
}
|
|
3812
|
+
const _publishLockErr = await this.assertLockAllowsWrite({
|
|
3813
|
+
type: request.type,
|
|
3814
|
+
name: request.name,
|
|
3815
|
+
...request.organizationId ? { organizationId: request.organizationId } : {},
|
|
3816
|
+
operation: "publish",
|
|
3817
|
+
...request.actor ? { actor: request.actor } : {},
|
|
3818
|
+
source: "protocol.publishMetaItem"
|
|
3819
|
+
});
|
|
3820
|
+
if (_publishLockErr) throw _publishLockErr;
|
|
3525
3821
|
await this.ensureOverlayIndex();
|
|
3526
3822
|
const orgId = request.organizationId ?? null;
|
|
3527
3823
|
const repo = this.getOverlayRepo(orgId);
|
|
@@ -3589,6 +3885,15 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3589
3885
|
err.status = 403;
|
|
3590
3886
|
throw err;
|
|
3591
3887
|
}
|
|
3888
|
+
const _rollbackLockErr = await this.assertLockAllowsWrite({
|
|
3889
|
+
type: request.type,
|
|
3890
|
+
name: request.name,
|
|
3891
|
+
...request.organizationId ? { organizationId: request.organizationId } : {},
|
|
3892
|
+
operation: "rollback",
|
|
3893
|
+
...request.actor ? { actor: request.actor } : {},
|
|
3894
|
+
source: "protocol.rollbackMetaItem"
|
|
3895
|
+
});
|
|
3896
|
+
if (_rollbackLockErr) throw _rollbackLockErr;
|
|
3592
3897
|
await this.ensureOverlayIndex();
|
|
3593
3898
|
const orgId = request.organizationId ?? null;
|
|
3594
3899
|
const repo = this.getOverlayRepo(orgId);
|
|
@@ -3735,6 +4040,14 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3735
4040
|
err.status = 403;
|
|
3736
4041
|
throw err;
|
|
3737
4042
|
}
|
|
4043
|
+
const lockErr = await this.assertLockAllowsDelete({
|
|
4044
|
+
type: request.type,
|
|
4045
|
+
name: request.name,
|
|
4046
|
+
...request.organizationId ? { organizationId: request.organizationId } : {},
|
|
4047
|
+
...request.actor ? { actor: request.actor } : {},
|
|
4048
|
+
source: "protocol.deleteMetaItem"
|
|
4049
|
+
});
|
|
4050
|
+
if (lockErr) throw lockErr;
|
|
3738
4051
|
}
|
|
3739
4052
|
const singularTypeForRepo = PLURAL_TO_SINGULAR3[request.type] ?? request.type;
|
|
3740
4053
|
const overlayAllowedForRepoDel = _ObjectStackProtocolImplementation.isOverlayAllowed(singularTypeForRepo);
|
|
@@ -3779,6 +4092,17 @@ var _ObjectStackProtocolImplementation = class _ObjectStackProtocolImplementatio
|
|
|
3779
4092
|
} catch {
|
|
3780
4093
|
}
|
|
3781
4094
|
}
|
|
4095
|
+
await this.recordMetadataAudit({
|
|
4096
|
+
type: request.type,
|
|
4097
|
+
name: request.name,
|
|
4098
|
+
organizationId: orgId,
|
|
4099
|
+
operation: "delete",
|
|
4100
|
+
outcome: "allowed",
|
|
4101
|
+
code: "ok",
|
|
4102
|
+
...request.actor ? { actor: request.actor } : {},
|
|
4103
|
+
source: "protocol.deleteMetaItem",
|
|
4104
|
+
note: targetState
|
|
4105
|
+
});
|
|
3782
4106
|
return {
|
|
3783
4107
|
success: true,
|
|
3784
4108
|
reset: true,
|