snipara-companion 4.2.1 → 4.2.2
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 +4 -0
- package/dist/index.js +75 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
Release notes for `snipara-companion`, newest first.
|
|
4
4
|
|
|
5
|
+
## 4.2.2
|
|
6
|
+
|
|
7
|
+
- Propagate collaboration guard failures and run the pre-commit guard before mutating staged files.
|
|
8
|
+
|
|
5
9
|
## 4.2.1
|
|
6
10
|
|
|
7
11
|
- Forward validation scope only to Sandbox commands that accept it, while preserving scoped coordinator runs.
|
package/dist/index.js
CHANGED
|
@@ -24106,9 +24106,11 @@ function loadCollaborationState(rootDir = process.cwd()) {
|
|
|
24106
24106
|
schemaVersion: "snipara.collaboration.v1",
|
|
24107
24107
|
updatedAt: typeof parsed.updatedAt === "string" ? parsed.updatedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
24108
24108
|
workSessionId: normalizeOptionalString3(parsed.workSessionId),
|
|
24109
|
-
workflowSessions: Object.fromEntries(
|
|
24110
|
-
(
|
|
24111
|
-
|
|
24109
|
+
workflowSessions: Object.fromEntries(
|
|
24110
|
+
Object.entries(parsed.workflowSessions ?? {}).filter(
|
|
24111
|
+
([key, value]) => /^[a-f0-9]{64}$/.test(key) && typeof value === "string" && value.length > 0
|
|
24112
|
+
)
|
|
24113
|
+
),
|
|
24112
24114
|
sessionId: normalizeOptionalString3(parsed.sessionId),
|
|
24113
24115
|
actorId: normalizeOptionalString3(parsed.actorId),
|
|
24114
24116
|
actorType: normalizeActorType(parsed.actorType),
|
|
@@ -24357,10 +24359,15 @@ async function workflowCollaborationStart(options) {
|
|
|
24357
24359
|
const session = hostedSession.status === "ok" ? hostedSession.data?.session : void 0;
|
|
24358
24360
|
const workSessionId = session?.id ?? persistedSessionId ?? logicalSessionId;
|
|
24359
24361
|
if (session) {
|
|
24360
|
-
state.workflowSessions = {
|
|
24362
|
+
state.workflowSessions = {
|
|
24363
|
+
...state.workflowSessions,
|
|
24364
|
+
[sessionKey]: session.id
|
|
24365
|
+
};
|
|
24361
24366
|
}
|
|
24362
24367
|
const effectiveResources = hostedSession.status === "ok" ? hostedSession.data?.resources ?? resources : resources;
|
|
24363
|
-
let hostedClaim = {
|
|
24368
|
+
let hostedClaim = {
|
|
24369
|
+
status: "skipped"
|
|
24370
|
+
};
|
|
24364
24371
|
const shouldClaim = options.mode === "full" || options.mode === "orchestrate";
|
|
24365
24372
|
if (hostedSession.status === "ok" && shouldClaim && (files.length > 0 || effectiveResources.length > 0)) {
|
|
24366
24373
|
hostedClaim = await maybeCreateHostedLeases(context, {
|
|
@@ -24895,7 +24902,9 @@ async function runCollaborationWatchTick(context, state, options) {
|
|
|
24895
24902
|
let heartbeatHosted = {
|
|
24896
24903
|
status: "skipped"
|
|
24897
24904
|
};
|
|
24898
|
-
let claimHosted = {
|
|
24905
|
+
let claimHosted = {
|
|
24906
|
+
status: "skipped"
|
|
24907
|
+
};
|
|
24899
24908
|
let releaseHosted = {
|
|
24900
24909
|
status: "skipped"
|
|
24901
24910
|
};
|
|
@@ -24942,7 +24951,9 @@ async function runCollaborationWatchTick(context, state, options) {
|
|
|
24942
24951
|
releaseHosted = await releaseHostedLeases(
|
|
24943
24952
|
context,
|
|
24944
24953
|
staleActiveLeases.map((lease) => lease.id),
|
|
24945
|
-
{
|
|
24954
|
+
{
|
|
24955
|
+
reason: "Released by collaboration watch because the resource is no longer active."
|
|
24956
|
+
}
|
|
24946
24957
|
);
|
|
24947
24958
|
const releasedIds = new Set(
|
|
24948
24959
|
releaseHosted.status === "ok" ? (releaseHosted.data ?? []).map((item) => item.lease.id) : staleActiveLeases.map((lease) => lease.id)
|
|
@@ -25044,30 +25055,58 @@ function deriveGuardProfileResources(profile, files) {
|
|
|
25044
25055
|
}
|
|
25045
25056
|
if (profile === "pre-deploy") {
|
|
25046
25057
|
resources.push(
|
|
25047
|
-
{
|
|
25048
|
-
|
|
25058
|
+
{
|
|
25059
|
+
kind: "DEPLOY",
|
|
25060
|
+
id: "production-deployment",
|
|
25061
|
+
label: "Production deployment"
|
|
25062
|
+
},
|
|
25063
|
+
{
|
|
25064
|
+
kind: "SURFACE",
|
|
25065
|
+
id: "deployment",
|
|
25066
|
+
label: "Deployment and infrastructure"
|
|
25067
|
+
}
|
|
25049
25068
|
);
|
|
25050
25069
|
}
|
|
25051
25070
|
if (profile === "migration" || profile === "schema") {
|
|
25052
25071
|
resources.push(
|
|
25053
|
-
{
|
|
25072
|
+
{
|
|
25073
|
+
kind: "SCHEMA",
|
|
25074
|
+
id: "prisma:tenant_snipara",
|
|
25075
|
+
label: "Prisma tenant_snipara schema"
|
|
25076
|
+
},
|
|
25054
25077
|
{ kind: "SURFACE", id: "database", label: "Database and schema" }
|
|
25055
25078
|
);
|
|
25056
25079
|
}
|
|
25057
25080
|
if (profile === "release-package") {
|
|
25058
|
-
resources.push({
|
|
25081
|
+
resources.push({
|
|
25082
|
+
kind: "SURFACE",
|
|
25083
|
+
id: "release-package",
|
|
25084
|
+
label: "Package release surface"
|
|
25085
|
+
});
|
|
25059
25086
|
}
|
|
25060
25087
|
if (profile === "pre-commit" || profile === "pre-push") {
|
|
25061
25088
|
if (files.some(isPrismaSchemaPath)) {
|
|
25062
25089
|
resources.push(
|
|
25063
|
-
{
|
|
25090
|
+
{
|
|
25091
|
+
kind: "SCHEMA",
|
|
25092
|
+
id: "prisma:tenant_snipara",
|
|
25093
|
+
label: "Prisma tenant_snipara schema"
|
|
25094
|
+
},
|
|
25064
25095
|
{ kind: "SURFACE", id: "database", label: "Database and schema" }
|
|
25065
25096
|
);
|
|
25066
25097
|
}
|
|
25067
25098
|
if (files.some(isDeploymentPath)) {
|
|
25068
25099
|
resources.push(
|
|
25069
|
-
{
|
|
25070
|
-
|
|
25100
|
+
{
|
|
25101
|
+
kind: "DEPLOY",
|
|
25102
|
+
id: "production-deployment",
|
|
25103
|
+
label: "Production deployment"
|
|
25104
|
+
},
|
|
25105
|
+
{
|
|
25106
|
+
kind: "SURFACE",
|
|
25107
|
+
id: "deployment",
|
|
25108
|
+
label: "Deployment and infrastructure"
|
|
25109
|
+
}
|
|
25071
25110
|
);
|
|
25072
25111
|
}
|
|
25073
25112
|
if (files.some((file) => file.endsWith("package.json") || file.includes("/package.json"))) {
|
|
@@ -25256,7 +25295,7 @@ function buildCollaborationGitHookBlock(hookName) {
|
|
|
25256
25295
|
const profile = hookName === "pre-push" ? "pre-push" : "pre-commit";
|
|
25257
25296
|
return [
|
|
25258
25297
|
collaborationHookBlockMarker(hookName, "start"),
|
|
25259
|
-
"# Atomically claim checkout git writes, then block unsafe parallel edits.",
|
|
25298
|
+
profile === "pre-commit" ? "# Request a cooperative checkout lease before changing the index." : "# Atomically claim checkout git writes, then block unsafe parallel edits.",
|
|
25260
25299
|
'if [ "${SNIPARA_COLLABORATION_GUARD:-1}" = "0" ]; then',
|
|
25261
25300
|
' echo "Snipara collaboration guard bypassed by SNIPARA_COLLABORATION_GUARD=0" >&2',
|
|
25262
25301
|
"else",
|
|
@@ -25270,7 +25309,7 @@ function buildCollaborationGitHookBlock(hookName) {
|
|
|
25270
25309
|
" return 127",
|
|
25271
25310
|
" fi",
|
|
25272
25311
|
" }",
|
|
25273
|
-
` snipara_companion_hook collaboration claim --resource SURFACE:checkout-git-write --mode EXCLUSIVE --ttl-seconds 300 --reason "${profile} git write" --json >/dev/null || true`,
|
|
25312
|
+
` snipara_companion_hook collaboration claim --resource SURFACE:checkout-git-write --mode EXCLUSIVE --ttl-seconds 300 --reason "${profile} git write" --json >/dev/null || ${profile === "pre-commit" ? "exit $?" : "true"}`,
|
|
25274
25313
|
" snipara_companion_guard() {",
|
|
25275
25314
|
` snipara_companion_hook collaboration guard --profile ${profile} --action ${profile} --resource SURFACE:checkout-git-write --enforce "$@" --json >/dev/null`,
|
|
25276
25315
|
" }",
|
|
@@ -25287,7 +25326,7 @@ function buildCollaborationGitHookBlock(hookName) {
|
|
|
25287
25326
|
" else",
|
|
25288
25327
|
" snipara_companion_guard",
|
|
25289
25328
|
" fi",
|
|
25290
|
-
"fi",
|
|
25329
|
+
profile === "pre-commit" ? "fi || exit $?" : "fi",
|
|
25291
25330
|
collaborationHookBlockMarker(hookName, "end")
|
|
25292
25331
|
].join("\n");
|
|
25293
25332
|
}
|
|
@@ -25303,6 +25342,15 @@ function mergeManagedCollaborationHookBlock(hookName, currentContent, block) {
|
|
|
25303
25342
|
${base}`;
|
|
25304
25343
|
const nextBlock = `${block}
|
|
25305
25344
|
`;
|
|
25345
|
+
if (hookName === "pre-commit") {
|
|
25346
|
+
const newline = withShebang.indexOf("\n");
|
|
25347
|
+
const shebang = newline < 0 ? withShebang : withShebang.slice(0, newline);
|
|
25348
|
+
const body = newline < 0 ? "" : withShebang.slice(newline + 1);
|
|
25349
|
+
return ensureTrailingNewline2(
|
|
25350
|
+
`${shebang}
|
|
25351
|
+
${nextBlock}${body.replace(managedBlockPattern, "")}`
|
|
25352
|
+
);
|
|
25353
|
+
}
|
|
25306
25354
|
if (managedBlockPattern.test(withShebang)) {
|
|
25307
25355
|
return ensureTrailingNewline2(withShebang.replace(managedBlockPattern, nextBlock));
|
|
25308
25356
|
}
|
|
@@ -25388,7 +25436,16 @@ function expireLocalLeases(state, now = /* @__PURE__ */ new Date()) {
|
|
|
25388
25436
|
}
|
|
25389
25437
|
}
|
|
25390
25438
|
function workflowSessionKey(context, workflowId) {
|
|
25391
|
-
return (0, import_node_crypto17.createHash)("sha256").update(
|
|
25439
|
+
return (0, import_node_crypto17.createHash)("sha256").update(
|
|
25440
|
+
JSON.stringify([
|
|
25441
|
+
context.config.apiUrl,
|
|
25442
|
+
context.config.projectId,
|
|
25443
|
+
context.actor.actorType,
|
|
25444
|
+
context.actor.actorId,
|
|
25445
|
+
context.worktree,
|
|
25446
|
+
workflowId
|
|
25447
|
+
])
|
|
25448
|
+
).digest("hex");
|
|
25392
25449
|
}
|
|
25393
25450
|
function workflowWorkSessionId(workflowId) {
|
|
25394
25451
|
return `workflow:${workflowId}`;
|