breakaway 2.0.0-main.76 → 2.0.0-main.78

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.
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "breakaway",
3
- "version": "2.0.0-main.76",
3
+ "version": "2.0.0-main.78",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "breakaway",
9
- "version": "2.0.0-main.76",
9
+ "version": "2.0.0-main.78",
10
10
  "license": "FSL-1.1-Apache-2.0",
11
11
  "bin": {
12
12
  "breakaway": "scripts/tasks.mjs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "breakaway",
3
- "version": "2.0.0-main.76",
3
+ "version": "2.0.0-main.78",
4
4
  "description": "The task board for you and your coding agents: a Cloudflare Worker, its web app, Taskwarrior sync, and the CLI (npx breakaway).",
5
5
  "license": "FSL-1.1-Apache-2.0",
6
6
  "type": "module",
@@ -225,8 +225,8 @@ const MAX_WORKERS = 50;
225
225
  const MAX_PAGES = 20;
226
226
 
227
227
  /**
228
- * Paths discover must never call: a KV value, an R2 object, or a Worker's code (BRK-188). Every call is checked against
229
- * these before it's made, so a bug can't turn a read of settings into a read of data.
228
+ * Paths discover must never call: a KV value, an R2 object, a Worker's code (BRK-188), or its logs (BRK-253). Every
229
+ * call is checked against these before it's made, so a bug can't turn a read of settings into a read of data.
230
230
  */
231
231
  export const NEVER_CALLED = [
232
232
  /\/storage\/kv\/namespaces\/[^/]+\/(values|keys|bulk)/u,
@@ -235,6 +235,9 @@ export const NEVER_CALLED = [
235
235
  /\/workers\/scripts\/[^/]+$/u,
236
236
  /\/versions\/[^/?]+\?.*include=modules/u,
237
237
  /\/secrets\/[^/]+$/u,
238
+ // Workers Observability's logs and telemetry, and a Worker's live tail: what its requests carried (BRK-253).
239
+ /\/workers\/observability\//u,
240
+ /\/workers\/scripts\/[^/]+\/tails/u,
238
241
  ];
239
242
 
240
243
  /** A permission as a 403 names it: with its legacy names in parentheses, for a token made before Cloudflare renamed it. */
@@ -70,7 +70,14 @@ export function checkSwitch(value, field) {
70
70
  * @param {{ target: string | null }} row
71
71
  * @param {string} worker the install's Worker
72
72
  */
73
- export const runsTheBoard = (row, worker) => Boolean(row.target) && row.target === worker;
73
+ export const runsTheBoard = (row, worker) => {
74
+ // Compared as names (BRK-253): ` Breakaway ` is still the install's Worker, so no spelling of it escapes observe only.
75
+ const name = (value) =>
76
+ String(value ?? '')
77
+ .trim()
78
+ .toLowerCase();
79
+ return Boolean(name(row.target)) && name(row.target) === name(worker);
80
+ };
74
81
 
75
82
  /**
76
83
  * The environment as the API shows it.
@@ -94,3 +94,26 @@ export function resourceView(row, environment, task) {
94
94
  seen: new Date(row.seen).toISOString(),
95
95
  };
96
96
  }
97
+
98
+ /** How often the cron refreshes a provider's inventory by itself (BRK-248). */
99
+ export const REFRESH_EVERY_MS = 15 * 60 * 1000;
100
+
101
+ /** At most this many providers refresh on one cron tick, the longest-waiting first, so they stagger. */
102
+ export const REFRESH_PER_TICK = 2;
103
+
104
+ /** A platform's answers that mean the token can't read: the cron stops trying until a new token is pasted. */
105
+ const REFUSED = new Set([401, 403]);
106
+
107
+ /**
108
+ * Whether the cron refreshes a provider now (BRK-248): never refreshed, or not in the last 15 minutes. One whose last
109
+ * refresh the platform refused (401 or 403) waits for a new token instead: Connections already says why.
110
+ * @param {{ at: number, ok: boolean, status: number | null } | null} last the provider's last refresh
111
+ * @param {number} now
112
+ * @param {number | null} [tokenEdited] when the provider's token was last pasted
113
+ */
114
+ export function refreshDue(last, now, tokenEdited = null) {
115
+ if (!last) return true;
116
+ if (!last.ok && last.status !== null && REFUSED.has(last.status) && !(tokenEdited !== null && tokenEdited > last.at))
117
+ return false;
118
+ return now - last.at >= REFRESH_EVERY_MS;
119
+ }
@@ -5,7 +5,8 @@
5
5
  # stops before it reads the write token. That token is CLOUDFLARE_API_TOKEN, a secret of the GitHub environment named
6
6
  # for the environment (for every short-lived environment, the one GitHub environment named short-lived), which only
7
7
  # {{branchName}} may use. It checks out none of this repository's code: it runs breakaway's runner, pinned to
8
- # {{version}}, and reports each step to the board. Agents never run this workflow.
8
+ # {{version}} and installed once, before any step holds the token, from the package's own lockfile with no install
9
+ # scripts, and reports each step to the board. Agents never run this workflow.
9
10
  name: Apply infrastructure
10
11
  run-name: Apply plan ${{ inputs.plan }} to ${{ inputs.environment }}
11
12
 
@@ -47,9 +48,9 @@ jobs:
47
48
  runs-on: ubuntu-latest
48
49
  timeout-minutes: 30
49
50
  environment: ${{ inputs.github_environment || inputs.environment }}
50
- # id-token proves to the board which repository, environment, workflow, and run asks for the plan.
51
+ # id-token proves to the board which repository, environment, workflow, and run asks for the plan. Nothing is
52
+ # checked out, so the run reads nothing of the repository.
51
53
  permissions:
52
- contents: read
53
54
  id-token: write
54
55
  env:
55
56
  BREAKAWAY_URL: ${{ vars.BREAKAWAY_URL }}
@@ -61,16 +62,22 @@ jobs:
61
62
  with:
62
63
  node-version: 22
63
64
 
65
+ # The only download: the package ships npm-shrinkwrap.json and has no dependencies, so this installs exactly
66
+ # what was published, and runs none of its scripts. The steps after it run that copy, so nothing is fetched while
67
+ # the write token is in a step's environment.
68
+ - name: Install the runner
69
+ run: npm install --global --ignore-scripts --no-audit --no-fund breakaway@{{version}}
70
+
64
71
  - name: Check the plan
65
- run: npx --yes breakaway@{{version}} infra runner check
72
+ run: breakaway infra runner check
66
73
 
67
74
  - name: Apply the plan
68
75
  env:
69
76
  BREAKAWAY_WRITE_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
70
- run: npx --yes breakaway@{{version}} infra runner apply
77
+ run: breakaway infra runner apply
71
78
 
72
79
  - name: Report the end
73
80
  if: always()
74
81
  env:
75
82
  OUTCOME: ${{ job.status }}
76
- run: npx --yes breakaway@{{version}} infra runner end
83
+ run: breakaway infra runner end