@akira-tl/forgerelay 0.9.3 → 0.10.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.
Files changed (109) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +10 -4
  3. package/dist/cli/init.js +111 -24
  4. package/dist/cli/maintenance-prune.js +479 -0
  5. package/dist/cli/maintenance-retention.js +93 -0
  6. package/dist/cli/maintenance.js +598 -0
  7. package/dist/cli/setup-support.js +21 -0
  8. package/dist/cli/shell/setup.js +99 -0
  9. package/dist/cli.js +72 -16
  10. package/dist/mcp/hooks/hooks.js +6 -3
  11. package/dist/mcp/oauth/public-url.js +3 -0
  12. package/dist/mcp/oauth/router.js +14 -9
  13. package/dist/mcp/process/process-platform.js +24 -26
  14. package/dist/mcp/process/process-sessions.js +6 -3
  15. package/dist/mcp/server/transport/http-server.js +17 -9
  16. package/dist/mcp/server/workspace/runtime/workspace-open-presentation.js +6 -0
  17. package/dist/mcp/server/workspace/runtime/workspace-tools.js +1 -1
  18. package/dist/mcp/server-instructions.js +10 -1
  19. package/dist/runtime/config/config.js +60 -6
  20. package/dist/runtime/instructions/shell-instructions.js +100 -0
  21. package/dist/runtime/security/runtime-privilege.js +120 -0
  22. package/dist/runtime/shell/command-shell-runtime.js +235 -0
  23. package/dist/runtime/state/runtime-lease.js +109 -0
  24. package/dist/ui/.vite/manifest.json +276 -276
  25. package/dist/ui/activity-panel-app.html +2 -2
  26. package/dist/ui/assets/{activity-panel-app-Sl1Jro8v.js → activity-panel-app-BkODhDLg.js} +1 -1
  27. package/dist/ui/assets/{activity-panel-app-7Xe0alhm.css → activity-panel-app-DkfJzTZ3.css} +1 -1
  28. package/dist/ui/assets/{angular-html-B_yn91wW.js → angular-html-DjuELMdF.js} +1 -1
  29. package/dist/ui/assets/{angular-ts-DSgtloKz.js → angular-ts-2EXVZIIX.js} +1 -1
  30. package/dist/ui/assets/{apl-NatWtF8X.js → apl-Bb4IeT5V.js} +1 -1
  31. package/dist/ui/assets/{astro-BYFEVBuN.js → astro-Bjavu3nT.js} +1 -1
  32. package/dist/ui/assets/{blade-DoO7yvMR.js → blade-DKW2uHZo.js} +1 -1
  33. package/dist/ui/assets/{c-Rl2hMCcg.js → c-oLeHmzbj.js} +1 -1
  34. package/dist/ui/assets/{cobol-ByC5mWiB.js → cobol-CcqFMr5T.js} +1 -1
  35. package/dist/ui/assets/{coffee-Dez77Qov.js → coffee-BA20zqRF.js} +1 -1
  36. package/dist/ui/assets/{cpp-DtaAQT9h.js → cpp-D750WmDa.js} +1 -1
  37. package/dist/ui/assets/{crystal-Bgmbf8ec.js → crystal-Cv5I6OMI.js} +1 -1
  38. package/dist/ui/assets/{css-C1tjBtVN.js → css-CjPPWPeH.js} +1 -1
  39. package/dist/ui/assets/{edge-DeH6u8Wg.js → edge-aYRuudEZ.js} +1 -1
  40. package/dist/ui/assets/{elixir-_H3KnmWT.js → elixir-ChLitmz7.js} +1 -1
  41. package/dist/ui/assets/{elm-CsCe3U28.js → elm-Fs7L7u36.js} +1 -1
  42. package/dist/ui/assets/{erb-CbM-L2g8.js → erb-B-qXHxN1.js} +1 -1
  43. package/dist/ui/assets/{git-rebase-D0s5pDh9.js → git-rebase-DOVN5OEg.js} +1 -1
  44. package/dist/ui/assets/{glimmer-js-BfOToq_A.js → glimmer-js-BFt_vCTW.js} +1 -1
  45. package/dist/ui/assets/{glimmer-ts-CCUOkL2K.js → glimmer-ts-ufCHlR6C.js} +1 -1
  46. package/dist/ui/assets/{glsl-DH4ec9dE.js → glsl-Ex4JXGuC.js} +1 -1
  47. package/dist/ui/assets/{graphql-DilAMBoI.js → graphql-pQPXtBk5.js} +1 -1
  48. package/dist/ui/assets/{hack-BDkNDZlF.js → hack-B5hDguhd.js} +1 -1
  49. package/dist/ui/assets/{haml-D_QBp6K7.js → haml-BrNeI29U.js} +1 -1
  50. package/dist/ui/assets/{handlebars-DePUrTpC.js → handlebars-DCqTsL9-.js} +1 -1
  51. package/dist/ui/assets/{heavy-payload-DOwZpO6n.js → heavy-payload-DsmmHgvt.js} +3 -3
  52. package/dist/ui/assets/{html-By4dNnM4.js → html-D8k0CC9V.js} +1 -1
  53. package/dist/ui/assets/{html-derivative-DDw9Ef4Q.js → html-derivative-CC8flWmC.js} +1 -1
  54. package/dist/ui/assets/{http-B0QxWc9M.js → http-BYnWqNep.js} +1 -1
  55. package/dist/ui/assets/{hurl-vMQ4lda1.js → hurl-BND-z85s.js} +1 -1
  56. package/dist/ui/assets/{java-DYRe2lWG.js → java-Dug0oB9T.js} +1 -1
  57. package/dist/ui/assets/{javascript-CxyGqwcL.js → javascript-oDJ7WITC.js} +1 -1
  58. package/dist/ui/assets/{jinja-JUwV-fZt.js → jinja-Cv0t_F1U.js} +1 -1
  59. package/dist/ui/assets/{jison-7ZqCEvS8.js → jison-Car3MF55.js} +1 -1
  60. package/dist/ui/assets/{json-dbltgiiA.js → json-CEViCsf4.js} +1 -1
  61. package/dist/ui/assets/{jsx-oDopT7YQ.js → jsx-BfZ0zgSH.js} +1 -1
  62. package/dist/ui/assets/{julia-CkKiNSav.js → julia-CmX0b3Tn.js} +1 -1
  63. package/dist/ui/assets/{just-DuqCAKJ3.js → just-BuugLCVk.js} +1 -1
  64. package/dist/ui/assets/{latex-sudcRDSn.js → latex-FpTXqO03.js} +1 -1
  65. package/dist/ui/assets/{liquid-Di-08Js7.js → liquid-B37OzUFu.js} +1 -1
  66. package/dist/ui/assets/{lua-YlqdMoV0.js → lua-BHjcb8oq.js} +1 -1
  67. package/dist/ui/assets/{marko-CJRNyJDb.js → marko-CApj_fsH.js} +1 -1
  68. package/dist/ui/assets/{mdc-t12CzZHs.js → mdc-Ed5vQWq8.js} +1 -1
  69. package/dist/ui/assets/{nginx-57-b4XwT.js → nginx-u_rVEBox.js} +1 -1
  70. package/dist/ui/assets/{nim-BzrswYQa.js → nim-Ba9EdchT.js} +1 -1
  71. package/dist/ui/assets/{perl-D9JR_iIh.js → perl-BpU_6Wvz.js} +1 -1
  72. package/dist/ui/assets/{php-Py2gFHil.js → php-bKabofky.js} +1 -1
  73. package/dist/ui/assets/{pug-PzLLy0h1.js → pug-C_aLNkqe.js} +1 -1
  74. package/dist/ui/assets/{qml-By8fwgV4.js → qml-D9VisnRy.js} +1 -1
  75. package/dist/ui/assets/{r-CcezTbLq.js → r-CYqB1sLx.js} +1 -1
  76. package/dist/ui/assets/{razor-dG-vdhL_.js → razor-DNJKI8Rs.js} +1 -1
  77. package/dist/ui/assets/{regexp-BlsQ-N_8.js → regexp-DHrTHXkz.js} +1 -1
  78. package/dist/ui/assets/{rst-C2awDCat.js → rst-CbNdSFHv.js} +1 -1
  79. package/dist/ui/assets/{ruby-zA2W_49d.js → ruby-FyKG-pkF.js} +1 -1
  80. package/dist/ui/assets/{sas-D49bhyaN.js → sas-BbSPDl3X.js} +1 -1
  81. package/dist/ui/assets/{scss-BQb-cp01.js → scss-2nX9g6gD.js} +1 -1
  82. package/dist/ui/assets/{shellscript-Dga4H_Ni.js → shellscript-CmON6x2x.js} +1 -1
  83. package/dist/ui/assets/{shellsession-n3-5CqcF.js → shellsession-DtqIGlAX.js} +1 -1
  84. package/dist/ui/assets/{soy-XYBOf_BA.js → soy-BzUJMmJT.js} +1 -1
  85. package/dist/ui/assets/{sql-ET4u5Cpl.js → sql-CgVcFZmb.js} +1 -1
  86. package/dist/ui/assets/{stata-CLHcJHO_.js → stata-CNitlMot.js} +1 -1
  87. package/dist/ui/assets/{surrealql-BdjQ60T4.js → surrealql-BA8-xsRZ.js} +1 -1
  88. package/dist/ui/assets/{svelte-B2RPtKJe.js → svelte-El02yAxv.js} +1 -1
  89. package/dist/ui/assets/{templ-CrByPW_W.js → templ-DeUQ84aR.js} +1 -1
  90. package/dist/ui/assets/{tex-DZBkg363.js → tex-Cu-FqpPS.js} +1 -1
  91. package/dist/ui/assets/{ts-tags-DJR3Gphb.js → ts-tags-X42N6TGA.js} +1 -1
  92. package/dist/ui/assets/{tsx-CajzROyy.js → tsx-C1aPp9rY.js} +1 -1
  93. package/dist/ui/assets/{twig-BZjk5Zda.js → twig-Cj1Q4SQc.js} +1 -1
  94. package/dist/ui/assets/{typescript-B-EWToLj.js → typescript-Du9lVt1G.js} +1 -1
  95. package/dist/ui/assets/{vue-D_rHCCr8.js → vue-_uMGbFv8.js} +1 -1
  96. package/dist/ui/assets/{vue-html-CC4WlvVt.js → vue-html-D61naG-Q.js} +1 -1
  97. package/dist/ui/assets/{vue-vine-BgNMVgpk.js → vue-vine-CkFae4yV.js} +1 -1
  98. package/dist/ui/assets/{xml-BI86-WbH.js → xml-Cbwsc6ws.js} +1 -1
  99. package/dist/ui/assets/{xsl-DXeLZV4J.js → xsl-NyBx72XB.js} +1 -1
  100. package/dist/ui/assets/{yaml-60_PFlWa.js → yaml-Cgb6Uq9u.js} +1 -1
  101. package/dist/workspaces/context.js +32 -5
  102. package/dist/workspaces/presentation/workspace-presentation.js +1 -0
  103. package/dist/workspaces/sessions.js +2 -0
  104. package/dist/workspaces.js +2 -1
  105. package/docs/configuration.md +101 -14
  106. package/package.json +2 -2
  107. package/scripts/release/release-gate.test.mjs +1 -0
  108. package/scripts/release-proof.mjs +85 -9
  109. package/scripts/release-proof.test.mjs +79 -1
@@ -1,6 +1,7 @@
1
1
  import assert from "node:assert/strict";
2
2
  import { execFile } from "node:child_process";
3
3
  import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
4
+ import { createServer } from "node:http";
4
5
  import { tmpdir } from "node:os";
5
6
  import { join } from "node:path";
6
7
  import test from "node:test";
@@ -21,10 +22,36 @@ async function runProof(cwd, action, env = {}) {
21
22
  });
22
23
  }
23
24
 
25
+ async function artifactApiEnv(t, { npmStatus = 404, githubStatus = 404 } = {}) {
26
+ const server = createServer((request, response) => {
27
+ if (request.url?.startsWith("/npm/")) response.statusCode = npmStatus;
28
+ else if (request.url?.startsWith("/github/")) response.statusCode = githubStatus;
29
+ else response.statusCode = 500;
30
+ response.end();
31
+ });
32
+ await new Promise((resolve, reject) => {
33
+ server.once("error", reject);
34
+ server.listen(0, "127.0.0.1", resolve);
35
+ });
36
+ t.after(() => new Promise((resolve) => server.close(resolve)));
37
+ const address = server.address();
38
+ assert.ok(address && typeof address === "object");
39
+ const base = `http://127.0.0.1:${address.port}`;
40
+ return {
41
+ NODE_ENV: "test",
42
+ FORGERELAY_TEST_NPM_REGISTRY_URL: `${base}/npm/`,
43
+ FORGERELAY_TEST_GITHUB_API_URL: `${base}/github/`,
44
+ };
45
+ }
46
+
24
47
  test("release tag hook gate uses repository facts instead of requiring a local proof", async (t) => {
25
48
  const root = await mkdtemp(join(tmpdir(), "forgerelay-release-proof-"));
26
49
  t.after(() => rm(root, { recursive: true, force: true }));
27
- await writeFile(join(root, "package.json"), JSON.stringify({ version: "1.2.3" }) + "\n");
50
+ await writeFile(join(root, "package.json"), JSON.stringify({
51
+ name: "@akira-tl/forgerelay",
52
+ version: "1.2.3",
53
+ repository: { url: "git+https://github.com/Akira-TL/forgerelay.git" },
54
+ }) + "\n");
28
55
  await mkdir(join(root, "docs", "releases"), { recursive: true });
29
56
  await writeFile(join(root, "docs", "releases", "v1.2.3.md"), "# v1.2.3\n\nDedicated notes.\n");
30
57
  await writeFile(join(root, "tracked.txt"), "verified\n");
@@ -93,6 +120,14 @@ test("release tag hook gate uses repository facts instead of requiring a local p
93
120
  await rm(join(root, "untracked.txt"));
94
121
  await git(root, ["add", "tracked.txt"]);
95
122
  await git(root, ["commit", "--allow-empty", "-m", "new head"]);
123
+ await runProof(root, "write");
124
+ const mutableEnv = await artifactApiEnv(t);
125
+ const deletion = await runProof(root, "check-hook", {
126
+ ...mutableEnv,
127
+ FORGERELAY_HOOK_PAYLOAD: JSON.stringify({ command: "git push --delete origin v1.2.3" }),
128
+ });
129
+ assert.match(deletion.stdout, /Release tag rebuild gate OK: v1\.2\.3/);
130
+
96
131
  await assert.rejects(
97
132
  () => runProof(root, "check-hook", {
98
133
  FORGERELAY_HOOK_PAYLOAD: JSON.stringify({ command: "git push origin v1.2.3" }),
@@ -104,6 +139,49 @@ test("release tag hook gate uses repository facts instead of requiring a local p
104
139
  );
105
140
  });
106
141
 
142
+ test("release tag hook gate refuses deletion after an irreversible release artifact exists", async (t) => {
143
+ const root = await mkdtemp(join(tmpdir(), "forgerelay-release-proof-"));
144
+ t.after(() => rm(root, { recursive: true, force: true }));
145
+ await writeFile(join(root, "package.json"), JSON.stringify({
146
+ name: "@akira-tl/forgerelay",
147
+ version: "1.3.0",
148
+ repository: { url: "git+https://github.com/Akira-TL/forgerelay.git" },
149
+ }) + "\n");
150
+ await mkdir(join(root, "docs", "releases"), { recursive: true });
151
+ await writeFile(join(root, "docs", "releases", "v1.3.0.md"), "# v1.3.0\n\nDedicated notes.\n");
152
+ await git(root, ["init"]);
153
+ await git(root, ["config", "user.email", "proof@example.com"]);
154
+ await git(root, ["config", "user.name", "Release Proof Test"]);
155
+ await git(root, ["add", "."]);
156
+ await git(root, ["commit", "-m", "release 1.3.0"]);
157
+ await git(root, ["tag", "v1.3.0"]);
158
+ await runProof(root, "write");
159
+
160
+ const npmPublishedEnv = await artifactApiEnv(t, { npmStatus: 200, githubStatus: 404 });
161
+ await assert.rejects(
162
+ () => runProof(root, "check-hook", {
163
+ ...npmPublishedEnv,
164
+ FORGERELAY_HOOK_PAYLOAD: JSON.stringify({ command: "git push --delete origin v1.3.0" }),
165
+ }),
166
+ (error) => {
167
+ assert.match(String(error.stderr ?? error), /npm package .* already exists/);
168
+ return true;
169
+ },
170
+ );
171
+
172
+ const githubPublishedEnv = await artifactApiEnv(t, { npmStatus: 404, githubStatus: 200 });
173
+ await assert.rejects(
174
+ () => runProof(root, "check-hook", {
175
+ ...githubPublishedEnv,
176
+ FORGERELAY_HOOK_PAYLOAD: JSON.stringify({ command: "git push --delete origin v1.3.0" }),
177
+ }),
178
+ (error) => {
179
+ assert.match(String(error.stderr ?? error), /GitHub Release .* already exists/);
180
+ return true;
181
+ },
182
+ );
183
+ });
184
+
107
185
  test("release tag hook gate rejects a matching tag when dedicated notes are missing", async (t) => {
108
186
  const root = await mkdtemp(join(tmpdir(), "forgerelay-release-proof-"));
109
187
  t.after(() => rm(root, { recursive: true, force: true }));