@bevel-software/platform-core-backend 0.12.0 → 0.12.1

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 (27) hide show
  1. package/THIRD-PARTY-NOTICES.md +4 -4
  2. package/dist/modules/kb-fs/clone-config.d.ts +40 -2
  3. package/dist/modules/kb-fs/clone-config.d.ts.map +1 -1
  4. package/dist/modules/kb-fs/clone-config.js +94 -2
  5. package/dist/modules/kb-fs/clone-config.js.map +1 -1
  6. package/dist/modules/workflow/workflow.service.d.ts +38 -0
  7. package/dist/modules/workflow/workflow.service.d.ts.map +1 -1
  8. package/dist/modules/workflow/workflow.service.js +112 -6
  9. package/dist/modules/workflow/workflow.service.js.map +1 -1
  10. package/dist/modules/workspace/startup/kb-git.d.ts.map +1 -1
  11. package/dist/modules/workspace/startup/kb-git.js +21 -4
  12. package/dist/modules/workspace/startup/kb-git.js.map +1 -1
  13. package/dist/modules/workspace/workspace.service.d.ts +52 -8
  14. package/dist/modules/workspace/workspace.service.d.ts.map +1 -1
  15. package/dist/modules/workspace/workspace.service.js +121 -23
  16. package/dist/modules/workspace/workspace.service.js.map +1 -1
  17. package/package.json +5 -5
  18. package/src/modules/kb-fs/__tests__/clone-config.test.ts +63 -2
  19. package/src/modules/kb-fs/clone-config.ts +97 -2
  20. package/src/modules/secrets-vault/secrets-vault.routes.ts +582 -582
  21. package/src/modules/workflow/__tests__/workflow.service.commitFileWhileLocked.test.ts +11 -5
  22. package/src/modules/workflow/__tests__/workflow.service.releaseLock.test.ts +172 -7
  23. package/src/modules/workflow/workflow.service.ts +118 -6
  24. package/src/modules/workspace/__tests__/workspace.service.test.ts +1 -1
  25. package/src/modules/workspace/startup/__tests__/kb-startup-runner.test.ts +141 -0
  26. package/src/modules/workspace/startup/kb-git.ts +20 -7
  27. package/src/modules/workspace/workspace.service.ts +132 -25
@@ -26,10 +26,10 @@ These are shippable alongside our own licence, but carry an obligation beyond
26
26
  attribution: modifications to *their own source files* must remain under the same
27
27
  licence and be made available. Using them as dependencies triggers nothing.
28
28
 
29
- - `@utcp/code-mode@1.2.12` — MPL-2.0
29
+ - `@utcp/code-mode@1.2.13` — MPL-2.0
30
30
  - `@utcp/direct-call@1.1.1` — MPL-2.0
31
31
  - `@utcp/http@1.1.11` — MPL-2.0
32
- - `@utcp/mcp@1.1.4` — MPL-2.0
32
+ - `@utcp/mcp@1.1.6` — MPL-2.0
33
33
  - `@utcp/sdk@1.1.2` — MPL-2.0
34
34
 
35
35
  ## Packages shipping no licence file
@@ -84,10 +84,10 @@ the declared licence; refer to the upstream project for the notice.
84
84
  - **@types/node@22.20.1** — MIT — see licence text #16 <https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node>
85
85
  - **@types/pg@8.20.0** — MIT — see licence text #16 <https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/pg>
86
86
  - **@types/unist@3.0.3** — MIT — see licence text #16 <https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/unist>
87
- - **@utcp/code-mode@1.2.12** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/code-mode#readme>
87
+ - **@utcp/code-mode@1.2.13** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/code-mode#readme>
88
88
  - **@utcp/direct-call@1.1.1** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/typescript-utcp#readme>
89
89
  - **@utcp/http@1.1.11** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/typescript-utcp#readme>
90
- - **@utcp/mcp@1.1.4** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/typescript-utcp#readme>
90
+ - **@utcp/mcp@1.1.6** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/typescript-utcp#readme>
91
91
  - **@utcp/sdk@1.1.2** — MPL-2.0 — see licence text #17 <https://github.com/universal-tool-calling-protocol/typescript-utcp#readme>
92
92
  - **@vercel/oidc@3.2.0** — Apache-2.0 — see licence text #18 <https://vercel.com>
93
93
  - **@workflow/serde@4.1.0-beta.2** — Apache-2.0 — see licence text #19 <https://github.com/vercel/workflow#readme>
@@ -1,6 +1,13 @@
1
1
  /**
2
- * The git configuration a per-branch workspace clone must have for its branch
3
- * to track exactly ONE upstream ref.
2
+ * The git configuration a per-branch workspace clone must carry: the tracking
3
+ * config that pins its branch to exactly ONE upstream ref, and the credential
4
+ * helper its remote operations authenticate with.
5
+ *
6
+ * Both are stamped at clone time AND re-stamped when an existing clone is
7
+ * adopted from disk, so a clone created by an older build — or by a path that
8
+ * only authenticated its own invocation — is repaired rather than left broken.
9
+ *
10
+ * On the tracking half:
4
11
  *
5
12
  * Why this exists: a clone's config is append-only from git's point of view,
6
13
  * and several things write to it:
@@ -58,4 +65,35 @@ export declare const SAFE_IMPLICIT_FETCH_ARGS: readonly string[];
58
65
  * workspace service) — no process is spawned here.
59
66
  */
60
67
  export declare function cloneTrackingConfigArgs(branch: string): string[][];
68
+ /**
69
+ * The inline credential helper a workspace clone authenticates its remote
70
+ * operations with, or null when the deployment has no git token configured.
71
+ *
72
+ * The snippet reads `$GITHUB_TOKEN` at CALL time, so the secret itself never
73
+ * enters argv, the clone's `.git/config`, or any error message quoting either.
74
+ * `GITHUB_TOKEN` is the normalised name — `CoreConfig` collapses `GIT_TOKEN` /
75
+ * `GH_TOKEN` onto it at boot, and `DeploymentSettingsService.syncGitTokenEnv`
76
+ * publishes a token supplied through the setup screen to the same place — so
77
+ * this one name covers every way a token can arrive.
78
+ *
79
+ * The username is provider-specific (GitHub `x-access-token`, GitLab `oauth2`,
80
+ * Bitbucket `x-token-auth`); the token is always the Basic-auth password,
81
+ * which every major host accepts.
82
+ */
83
+ export declare function credentialHelperValue(gitUsername: string): string | null;
84
+ /**
85
+ * `git clone` arguments that PERSIST the credential helper into the repository
86
+ * being created. Position is load-bearing: these belong AFTER the `clone`
87
+ * subcommand, where `--config` means "write this into the new repo's config".
88
+ * The same pair placed BEFORE it is git's per-invocation `-c`, which
89
+ * authenticates that one clone and leaves the resulting repo with no helper at
90
+ * all — so every later `git push` from that clone prompts for a username,
91
+ * finds no tty, and dies. That was a real outage: a self-hosted deployment
92
+ * cloned fine, committed fine, and silently pushed nothing for two days.
93
+ *
94
+ * Empty when no token is configured, matching the un-authenticated clone the
95
+ * rest of the layer already supports.
96
+ */
97
+ export declare function cloneCredentialArgs(gitUsername: string): string[];
98
+ export declare function cloneCredentialConfigArgs(gitUsername: string): string[][];
61
99
  //# sourceMappingURL=clone-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clone-config.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,wCAAwC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAErD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAMlE"}
1
+ {"version":3,"file":"clone-config.d.ts","sourceRoot":"","sources":["../../../src/modules/kb-fs/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,oBAAoB,wCAAwC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAErD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CAMlE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAiBxE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAGjE;AA2BD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,CASzE"}
@@ -1,6 +1,13 @@
1
1
  /**
2
- * The git configuration a per-branch workspace clone must have for its branch
3
- * to track exactly ONE upstream ref.
2
+ * The git configuration a per-branch workspace clone must carry: the tracking
3
+ * config that pins its branch to exactly ONE upstream ref, and the credential
4
+ * helper its remote operations authenticate with.
5
+ *
6
+ * Both are stamped at clone time AND re-stamped when an existing clone is
7
+ * adopted from disk, so a clone created by an older build — or by a path that
8
+ * only authenticated its own invocation — is repaired rather than left broken.
9
+ *
10
+ * On the tracking half:
4
11
  *
5
12
  * Why this exists: a clone's config is append-only from git's point of view,
6
13
  * and several things write to it:
@@ -66,4 +73,89 @@ export function cloneTrackingConfigArgs(branch) {
66
73
  ['config', '--replace-all', `branch.${branch}.merge`, `refs/heads/${branch}`],
67
74
  ];
68
75
  }
76
+ /**
77
+ * The inline credential helper a workspace clone authenticates its remote
78
+ * operations with, or null when the deployment has no git token configured.
79
+ *
80
+ * The snippet reads `$GITHUB_TOKEN` at CALL time, so the secret itself never
81
+ * enters argv, the clone's `.git/config`, or any error message quoting either.
82
+ * `GITHUB_TOKEN` is the normalised name — `CoreConfig` collapses `GIT_TOKEN` /
83
+ * `GH_TOKEN` onto it at boot, and `DeploymentSettingsService.syncGitTokenEnv`
84
+ * publishes a token supplied through the setup screen to the same place — so
85
+ * this one name covers every way a token can arrive.
86
+ *
87
+ * The username is provider-specific (GitHub `x-access-token`, GitLab `oauth2`,
88
+ * Bitbucket `x-token-auth`); the token is always the Basic-auth password,
89
+ * which every major host accepts.
90
+ */
91
+ export function credentialHelperValue(gitUsername) {
92
+ if (!process.env.GITHUB_TOKEN)
93
+ return null;
94
+ // Interpolated into a shell snippet that git will execute. `CoreConfig` and
95
+ // `DeploymentSettingsService` both reject a username outside this charset
96
+ // before it can get this far, so reaching the throw means an unvalidated
97
+ // fourth path appeared — fail closed rather than emit an injectable helper.
98
+ if (!/^[A-Za-z0-9._-]+$/.test(gitUsername)) {
99
+ throw new Error(`git username must match [A-Za-z0-9._-]+; got "${gitUsername}"`);
100
+ }
101
+ // printf '%s' rather than echo: POSIX leaves echo's handling of backslash
102
+ // escapes implementation-defined (dash interprets \c as "stop output"), so
103
+ // a token containing a backslash sequence could be silently truncated on
104
+ // the way to git. printf %s passes the bytes through verbatim. The literal
105
+ // `password=$GITHUB_TOKEN` stays in the snippet, which is what
106
+ // APP_HELPER_VALUE_PATTERN keys on — echo-era helpers stamped by earlier
107
+ // builds still match it and get replaced on the next stamp.
108
+ return `!f() { printf '%s\\n' "username=${gitUsername}" "password=$GITHUB_TOKEN"; }; f`;
109
+ }
110
+ /**
111
+ * `git clone` arguments that PERSIST the credential helper into the repository
112
+ * being created. Position is load-bearing: these belong AFTER the `clone`
113
+ * subcommand, where `--config` means "write this into the new repo's config".
114
+ * The same pair placed BEFORE it is git's per-invocation `-c`, which
115
+ * authenticates that one clone and leaves the resulting repo with no helper at
116
+ * all — so every later `git push` from that clone prompts for a username,
117
+ * finds no tty, and dies. That was a real outage: a self-hosted deployment
118
+ * cloned fine, committed fine, and silently pushed nothing for two days.
119
+ *
120
+ * Empty when no token is configured, matching the un-authenticated clone the
121
+ * rest of the layer already supports.
122
+ */
123
+ export function cloneCredentialArgs(gitUsername) {
124
+ const helper = credentialHelperValue(gitUsername);
125
+ return helper ? ['--config', `credential.helper=${helper}`] : [];
126
+ }
127
+ /**
128
+ * `git` argument lists that bring a clone's credential helper into line with
129
+ * the deployment's current config — the repair path for clones on disk (see
130
+ * `cloneCredentialArgs`), applied wherever `cloneTrackingConfigArgs` is:
131
+ * `--replace-all` when a token is configured (idempotent re-stamp, stale
132
+ * values collapse), `--unset-all` when the deployment lost its token (a
133
+ * leftover helper answering with an empty password must not shadow whatever
134
+ * auth the operator fell back to; unset of a missing value exits non-zero
135
+ * and callers tolerate it — see `stampCredentialHelper`). Both operations
136
+ * are scoped by the value pattern below so only app-owned helpers are
137
+ * touched. Returns the arguments rather than running them, for the same
138
+ * reason `cloneTrackingConfigArgs` does.
139
+ */
140
+ /**
141
+ * Value pattern (a POSIX ERE, as `git config`'s optional value-pattern
142
+ * argument expects) that matches ONLY helpers this application stamped —
143
+ * every one of ours reads `password=$GITHUB_TOKEN`, and no operator-authored
144
+ * helper has a reason to contain that literal. Scoping both the replace and
145
+ * the unset to it means an operator's own clone-local helper (`store`,
146
+ * `cache`, something custom) is never collapsed away or deleted by our
147
+ * stamping: git chains all configured helpers in order, so ours and theirs
148
+ * coexist.
149
+ */
150
+ const APP_HELPER_VALUE_PATTERN = 'password=\\$GITHUB_TOKEN';
151
+ export function cloneCredentialConfigArgs(gitUsername) {
152
+ const helper = credentialHelperValue(gitUsername);
153
+ // `--replace-all key value pattern` replaces every line MATCHING the
154
+ // pattern with the one value (adding it when none match) and leaves
155
+ // non-matching values — operator helpers — untouched. Same scoping on the
156
+ // unset: only app-stamped values are removed when the token goes away.
157
+ return helper
158
+ ? [['config', '--replace-all', 'credential.helper', helper, APP_HELPER_VALUE_PATTERN]]
159
+ : [['config', '--unset-all', 'credential.helper', APP_HELPER_VALUE_PATTERN]];
160
+ }
69
161
  //# sourceMappingURL=clone-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"clone-config.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,QAAQ;CACtD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO;QACL,CAAC,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,CAAC;QACxE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,SAAS,EAAE,QAAQ,CAAC;QAChE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,QAAQ,EAAE,cAAc,MAAM,EAAE,CAAC;KAC9E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"clone-config.js","sourceRoot":"","sources":["../../../src/modules/kb-fs/clone-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AAE1E;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAsB;IACzD,OAAO,EAAE,SAAS,EAAE,uBAAuB,EAAE,QAAQ;CACtD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO;QACL,CAAC,QAAQ,EAAE,eAAe,EAAE,qBAAqB,EAAE,oBAAoB,CAAC;QACxE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,SAAS,EAAE,QAAQ,CAAC;QAChE,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,MAAM,QAAQ,EAAE,cAAc,MAAM,EAAE,CAAC;KAC9E,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAC3C,4EAA4E;IAC5E,0EAA0E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CAAC,iDAAiD,WAAW,GAAG,CAAC,CAAC;IACnF,CAAC;IACD,0EAA0E;IAC1E,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,+DAA+D;IAC/D,yEAAyE;IACzE,4DAA4D;IAC5D,OAAO,mCAAmC,WAAW,kCAAkC,CAAC;AAC1F,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,MAAM,MAAM,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAClD,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,EAAE,qBAAqB,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACnE,CAAC;AAED;;;;;;;;;;;;GAYG;AACH;;;;;;;;;GASG;AACH,MAAM,wBAAwB,GAAG,0BAA0B,CAAC;AAE5D,MAAM,UAAU,yBAAyB,CAAC,WAAmB;IAC3D,MAAM,MAAM,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;IAClD,qEAAqE;IACrE,oEAAoE;IACpE,0EAA0E;IAC1E,uEAAuE;IACvE,OAAO,MAAM;QACX,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,EAAE,wBAAwB,CAAC,CAAC;QACtF,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,aAAa,EAAE,mBAAmB,EAAE,wBAAwB,CAAC,CAAC,CAAC;AACjF,CAAC"}
@@ -297,6 +297,44 @@ export declare class WorkflowService implements IWorkflowService {
297
297
  systemAuthorized?: boolean;
298
298
  skipValidation?: boolean;
299
299
  }): Promise<void>;
300
+ /**
301
+ * Workspaces whose last push failed. Purely so the recovery event fires on
302
+ * the transition back to healthy instead of on every subsequent save — a
303
+ * push runs on every write, and the healthy case must stay silent.
304
+ *
305
+ * Process-local and deliberately not persisted: a restart clears it, and the
306
+ * worst that costs is one redundant `git-sync-recovered` on a workspace that
307
+ * was already fine, which clients treat as a no-op.
308
+ */
309
+ private readonly gitSyncFailing;
310
+ /**
311
+ * Announce that a push landed. Emits only when this workspace was previously
312
+ * failing — see `gitSyncFailing`.
313
+ */
314
+ private noteGitSyncOk;
315
+ /**
316
+ * Announce that a commit is sitting locally because its push failed.
317
+ *
318
+ * This is the visibility half of the failure paths below; it never changes
319
+ * what they DO. The commit is already safe on disk and the retry / hand-off
320
+ * machinery is unaffected — all this adds is that someone finds out, rather
321
+ * than the deployment looking healthy while nothing reaches the remote.
322
+ */
323
+ private noteGitSyncFailed;
324
+ /**
325
+ * A bare push wrapped in the sync tracker: a failure raises the banner, a
326
+ * success clears it. For the workflow paths that push directly — sharing a
327
+ * branch, publishing a CR's source, update-from-base, the decline revert,
328
+ * the roles.yaml restore — rather than through `pushWithRecovery`'s
329
+ * cooperative ladder. Behaviour is otherwise unchanged: the error still
330
+ * propagates to the caller exactly as the bare push's did. Without this,
331
+ * those pushes could fail invisibly (no banner) and, worse, a successful
332
+ * share could not CLEAR a banner an earlier save had raised.
333
+ *
334
+ * The branch is derived from the workspace id (they are the same string,
335
+ * URL-encoding aside) so call sites cannot pass a mismatched pair.
336
+ */
337
+ private trackedPush;
300
338
  /**
301
339
  * Shared implementation of "push, and on non-fast-forward try a
302
340
  * cooperative pull-rebase + retry, then hand off to the agent if that
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.service.d.ts","sourceRoot":"","sources":["../../../src/modules/workflow/workflow.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow.service.d.ts","sourceRoot":"","sources":["../../../src/modules/workflow/workflow.service.ts"],"names":[],"mappings":"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"}
@@ -23,7 +23,8 @@ import { promisify } from 'node:util';
23
23
  import { isProtectedBranch, DEFAULT_BRANCH } from '@bevel-software/platform-shared';
24
24
  import { and, eq } from 'drizzle-orm';
25
25
  import { changeRequests } from '../database/schema.js';
26
- import { workspaceIdForBranch } from '../../shared/workspace-id.js';
26
+ import { workspaceIdForBranch, branchForWorkspaceId } from '../../shared/workspace-id.js';
27
+ import { sanitizeError } from './sanitize-error.js';
27
28
  import { WorkflowHooks } from './workflow-hooks.js';
28
29
  import { WorkspaceMutex } from '../kb-fs/mutex.js';
29
30
  import { hashEmail } from '../../shared/hash-email.js';
@@ -285,7 +286,7 @@ export class WorkflowService {
285
286
  // `discardWorkingChanges` removed: under save=share there's nothing dirty
286
287
  // to discard.
287
288
  shareCurrentBranch(workspaceId, user) {
288
- return this.git.push(workspaceId, user);
289
+ return this.trackedPush(workspaceId, user);
289
290
  }
290
291
  refreshRemotes(workspaceId) {
291
292
  return this.git.fetch(workspaceId);
@@ -528,6 +529,7 @@ export class WorkflowService {
528
529
  if (change) {
529
530
  try {
530
531
  await this.git.push(workspaceId, user);
532
+ this.noteGitSyncOk(workspaceId, branch);
531
533
  }
532
534
  catch (err) {
533
535
  // Non-fast-forward recovery on the autosave path: try the
@@ -544,17 +546,34 @@ export class WorkflowService {
544
546
  const detail = err instanceof Error ? err.message : String(err);
545
547
  const looksLikeNonFastForward = /non-fast-forward|rejected|fetch first|updates were rejected/i.test(detail);
546
548
  let recovered = false;
549
+ let recoveryError = null;
547
550
  if (looksLikeNonFastForward) {
548
551
  try {
549
552
  await this.git.pull(workspaceId);
550
553
  await this.git.push(workspaceId, user);
551
554
  recovered = true;
555
+ this.noteGitSyncOk(workspaceId, branch);
552
556
  }
553
557
  catch (recoveryErr) {
558
+ recoveryError = recoveryErr;
554
559
  console.warn('[workflow] autosave cooperative recovery (pull-rebase) failed; leaving the unpushed commit for the next save / releaseLock to surface:', recoveryErr instanceof Error ? recoveryErr.message : recoveryErr);
555
560
  }
556
561
  }
557
562
  if (!recovered) {
563
+ // Still best-effort — we don't fail the autosave. What gets the
564
+ // BANNER is only the class that cannot clear itself: auth or host
565
+ // failures, which no later attempt fixes. A non-fast-forward here —
566
+ // recovery attempted or not — is the routine two-editors race the
567
+ // surrounding flow already handles: the release push retries it,
568
+ // and if THAT fails the user gets the typed agent hand-off plus the
569
+ // banner from `pushWithRecovery`. Bannering it from a background
570
+ // autosave would tell an author mid-keystroke that the deployment
571
+ // is broken over a race that usually settles on its own — while an
572
+ // auth failure swallowed into a log line is how a broken deployment
573
+ // once stacked 136 local commits before anyone found out.
574
+ if (!looksLikeNonFastForward) {
575
+ this.noteGitSyncFailed(workspaceId, branch, recoveryError ?? err);
576
+ }
558
577
  console.warn('[workflow] push after autosave commit failed (commit landed locally):', detail);
559
578
  }
560
579
  }
@@ -706,6 +725,81 @@ export class WorkflowService {
706
725
  // converges on. Backend reactors (catalog invalidation, id-repair) hook here.
707
726
  this.fileChanges?.emit({ workspaceId, branch, paths: [targetPath], byUser: user });
708
727
  }
728
+ /**
729
+ * Workspaces whose last push failed. Purely so the recovery event fires on
730
+ * the transition back to healthy instead of on every subsequent save — a
731
+ * push runs on every write, and the healthy case must stay silent.
732
+ *
733
+ * Process-local and deliberately not persisted: a restart clears it, and the
734
+ * worst that costs is one redundant `git-sync-recovered` on a workspace that
735
+ * was already fine, which clients treat as a no-op.
736
+ */
737
+ gitSyncFailing = new Set();
738
+ /**
739
+ * Announce that a push landed. Emits only when this workspace was previously
740
+ * failing — see `gitSyncFailing`.
741
+ */
742
+ noteGitSyncOk(workspaceId, branch) {
743
+ // Callers hand this both spellings of a workspace id — HTTP routes pass
744
+ // the Express-decoded `user/feat`, internal callers (the pending-commits
745
+ // worker, the agent filesystem) the encoded `user%2Ffeat`. Keyed raw, a
746
+ // failure recorded by one caller could never be cleared by the other's
747
+ // success, and the banner would stick. Canonicalize the key AND the
748
+ // emitted id so every consumer sees one spelling.
749
+ const id = branchForWorkspaceId(workspaceId);
750
+ if (!this.gitSyncFailing.delete(id))
751
+ return;
752
+ console.log(`[workflow] git sync recovered for workspace=${id} branch=${branch}`);
753
+ this.events?.emit({ kind: 'git-sync-recovered', workspaceId: id, branch });
754
+ }
755
+ /**
756
+ * Announce that a commit is sitting locally because its push failed.
757
+ *
758
+ * This is the visibility half of the failure paths below; it never changes
759
+ * what they DO. The commit is already safe on disk and the retry / hand-off
760
+ * machinery is unaffected — all this adds is that someone finds out, rather
761
+ * than the deployment looking healthy while nothing reaches the remote.
762
+ */
763
+ noteGitSyncFailed(workspaceId, branch, err) {
764
+ // Same canonicalization as `noteGitSyncOk` — the pair must agree on keys.
765
+ const id = branchForWorkspaceId(workspaceId);
766
+ this.gitSyncFailing.add(id);
767
+ this.events?.emit({
768
+ kind: 'git-sync-failed',
769
+ workspaceId: id,
770
+ branch,
771
+ // Git stderr can quote a credentialed URL; the banner is user-facing and
772
+ // the string also lands in client logs, so sanitize before it leaves.
773
+ reason: sanitizeError(err),
774
+ });
775
+ }
776
+ /**
777
+ * A bare push wrapped in the sync tracker: a failure raises the banner, a
778
+ * success clears it. For the workflow paths that push directly — sharing a
779
+ * branch, publishing a CR's source, update-from-base, the decline revert,
780
+ * the roles.yaml restore — rather than through `pushWithRecovery`'s
781
+ * cooperative ladder. Behaviour is otherwise unchanged: the error still
782
+ * propagates to the caller exactly as the bare push's did. Without this,
783
+ * those pushes could fail invisibly (no banner) and, worse, a successful
784
+ * share could not CLEAR a banner an earlier save had raised.
785
+ *
786
+ * The branch is derived from the workspace id (they are the same string,
787
+ * URL-encoding aside) so call sites cannot pass a mismatched pair.
788
+ */
789
+ async trackedPush(workspaceId, user, opts) {
790
+ const branch = branchForWorkspaceId(workspaceId);
791
+ try {
792
+ // Preserve the exact call shape of the bare pushes this replaces — an
793
+ // explicit `undefined` third argument is a different call signature to
794
+ // every spy that asserts on it.
795
+ await (opts ? this.git.push(workspaceId, user, opts) : this.git.push(workspaceId, user));
796
+ this.noteGitSyncOk(workspaceId, branch);
797
+ }
798
+ catch (err) {
799
+ this.noteGitSyncFailed(workspaceId, branch, err);
800
+ throw err;
801
+ }
802
+ }
709
803
  /**
710
804
  * Shared implementation of "push, and on non-fast-forward try a
711
805
  * cooperative pull-rebase + retry, then hand off to the agent if that
@@ -715,25 +809,37 @@ export class WorkflowService {
715
809
  async pushWithRecovery(workspaceId, branch, targetPath, user, opts) {
716
810
  try {
717
811
  await this.git.push(workspaceId, user, opts);
812
+ this.noteGitSyncOk(workspaceId, branch);
718
813
  }
719
814
  catch (firstPushErr) {
720
815
  const firstDetail = firstPushErr instanceof Error ? firstPushErr.message : String(firstPushErr);
721
816
  const looksLikeNonFastForward = /non-fast-forward|rejected|fetch first|updates were rejected/i.test(firstDetail);
722
817
  let recovered = false;
723
818
  let recoveryDetail = '(cooperative path not attempted)';
819
+ let recoveryError = null;
724
820
  if (looksLikeNonFastForward) {
725
821
  try {
726
822
  await this.git.pull(workspaceId);
727
823
  await this.git.push(workspaceId, user, opts);
728
824
  recovered = true;
825
+ this.noteGitSyncOk(workspaceId, branch);
729
826
  console.log(`[workflow] non-fast-forward push recovered via pull --rebase for workspace=${workspaceId} branch=${branch} path=${targetPath}`);
730
827
  }
731
828
  catch (recoveryErr) {
829
+ recoveryError = recoveryErr;
732
830
  recoveryDetail = recoveryErr instanceof Error ? recoveryErr.message : String(recoveryErr);
733
831
  console.warn(`[workflow] cooperative recovery (pull-rebase) failed for workspace=${workspaceId} user=${user.id}; handing off to agent:`, recoveryDetail);
734
832
  }
735
833
  }
736
834
  if (!recovered) {
835
+ // Banner first, then the typed throw. The throw only reaches a UI that
836
+ // is still mounted and listening — the release fired as an editor
837
+ // unmounts has nowhere to surface it — whereas the event reaches every
838
+ // session on the branch regardless of what triggered the push.
839
+ // When recovery RAN, its error is the current state of the world (the
840
+ // first rejection may be a stale non-fast-forward the pull already
841
+ // cured); when it was skipped, the first error is all there is.
842
+ this.noteGitSyncFailed(workspaceId, branch, recoveryError ?? firstPushErr);
737
843
  console.warn(`[workflow] push failed for workspace=${workspaceId} user=${user.id}; throwing PushNeedsAgentResolutionError so the frontend can hand off to the agent:`, firstDetail);
738
844
  throw new PushNeedsAgentResolutionError(branch, targetPath, firstDetail, recoveryDetail);
739
845
  }
@@ -938,7 +1044,7 @@ export class WorkflowService {
938
1044
  // Push the source — `gh pr create` against an unpushed branch returns
939
1045
  // "head branch does not exist on remote". Push *after* the auto-merge
940
1046
  // so the remote sees the merge commit too.
941
- await this.git.push(workspaceId, user);
1047
+ await this.trackedPush(workspaceId, user);
942
1048
  const workspacePath = await this.workspaceService.getWorkspacePath(workspaceId);
943
1049
  const cwd = path.join(workspacePath, this.kbDirName);
944
1050
  // Touched paths between target and source — basis for the
@@ -1045,7 +1151,7 @@ export class WorkflowService {
1045
1151
  // If a new merge commit landed, push so the CR picks it up. When
1046
1152
  // already up to date there's nothing to share — short-circuit the push.
1047
1153
  if (!outcome.alreadyUpToDate) {
1048
- await this.git.push(workspaceId, user);
1154
+ await this.trackedPush(workspaceId, user);
1049
1155
  }
1050
1156
  this.prs.invalidateDetailCache(number);
1051
1157
  const refreshed = await this.prs.getPrDetail(number, {
@@ -1154,7 +1260,7 @@ export class WorkflowService {
1154
1260
  try {
1155
1261
  await this.git.restorePathFromRef(ws.id, mergeBase, repoRelPath);
1156
1262
  await this.git.commitFile(ws.id, user, repoRelPath, `Revert ${repoRelPath} (declined in change request #${number})`, true);
1157
- await this.git.push(ws.id, user);
1263
+ await this.trackedPush(ws.id, user);
1158
1264
  }
1159
1265
  finally {
1160
1266
  // Committed inline — drop the lock row directly rather than enqueueing
@@ -1615,7 +1721,7 @@ export class WorkflowService {
1615
1721
  if (!committed) {
1616
1722
  throw new Error('roles.yaml restore produced no commit while origin still diverges from base — source workspace out of sync; refusing to merge');
1617
1723
  }
1618
- await this.git.push(ws.id, user);
1724
+ await this.trackedPush(ws.id, user);
1619
1725
  this.accessControl.invalidate(ws.id);
1620
1726
  return true;
1621
1727
  }