breakaway 2.0.0-main.84 → 2.0.0-main.86

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.84",
3
+ "version": "2.0.0-main.86",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "breakaway",
9
- "version": "2.0.0-main.84",
9
+ "version": "2.0.0-main.86",
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.84",
3
+ "version": "2.0.0-main.86",
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",
@@ -1213,32 +1213,44 @@ export function zonesOf(resources) {
1213
1213
  * zone) is one the environment's routes or custom domains use; `account` when it names no Worker, zone, or hostname
1214
1214
  * (it's about the account or the platform, and the board keeps one per provider, not one per environment); or null
1215
1215
  * when it's another environment's, or no environment's.
1216
+ *
1217
+ * With `elsewhere`, the resources of the provider's other environments, an alert naming a zone or hostname that
1218
+ * neither this environment nor any other uses is `account` too (BRK-256), still on that zone or hostname, rather than
1219
+ * nobody's. A zone named only by its ID, which nothing here can name, stays nobody's.
1216
1220
  * @param {ReturnType<typeof alertFields>} fields
1217
1221
  * @param {Array<{ kind: string, name: string, attrs?: Record<string, unknown> }>} resources
1222
+ * @param {Array<{ kind: string, name: string, attrs?: Record<string, unknown> }>} [elsewhere]
1218
1223
  * @returns {{ resource: string | null, account: boolean, on: string | null } | null}
1219
1224
  */
1220
- export function alertPlace(fields, resources) {
1225
+ export function alertPlace(fields, resources, elsewhere) {
1221
1226
  if (fields.worker) {
1222
1227
  const mine = (resources ?? []).some((r) => r.kind === 'worker' && r.name === fields.worker);
1223
1228
  return mine ? { resource: rid('worker', fields.worker), account: false, on: fields.worker } : null;
1224
1229
  }
1225
1230
  if (!fields.zone && !fields.hostname && !fields.zoneId) return { resource: null, account: true, on: null };
1231
+ const on = fields.hostname ?? fields.zone;
1232
+ if (zoneUsed(fields, resources)) return { resource: null, account: false, on };
1233
+ if (elsewhere && on && !zoneUsed(fields, elsewhere)) return { resource: null, account: true, on };
1234
+ return null;
1235
+ }
1236
+
1237
+ /** Whether the zone an alert names, or its hostname's zone, is one that `resources`' routes or custom domains use. */
1238
+ function zoneUsed(fields, resources) {
1226
1239
  const zones = zonesOf(resources);
1227
1240
  const host = fields.hostname;
1228
- const zone =
1229
- (fields.zone && zones.has(fields.zone) ? fields.zone : null) ??
1230
- (host ? [...zones].find((z) => host === z || host.endsWith(`.${z}`)) : null) ??
1231
- null;
1232
- return zone ? { resource: null, account: false, on: host ?? zone } : null;
1241
+ return Boolean(
1242
+ (fields.zone && zones.has(fields.zone)) || (host && [...zones].some((z) => host === z || host.endsWith(`.${z}`))),
1243
+ );
1233
1244
  }
1234
1245
 
1235
1246
  /**
1236
1247
  * The account's alerts since `since`, from its alert history (`GET …/alerting/v3/history`, Notifications Read), as
1237
1248
  * `alert` signals placed by `alertPlace` (BRK-255): on the Worker it names when that Worker is in the environment, on
1238
1249
  * the whole environment when it names a zone or hostname the environment uses, and marked `account` when it names
1239
- * none of them; an alert about another environment's Worker or zone is left out. A zone named only by its ID is
1240
- * looked up in the account's zones (Zone Read). Oldest first. The board's alert webhook reports the same alerts as
1241
- * they fire; the store keeps one of each, and one of each account-wide alert across the provider's environments.
1250
+ * none of them, or (given `ctx.elsewhere`, BRK-256) a zone or hostname no environment uses; an alert about another
1251
+ * environment's Worker or zone is left out. A zone named only by its ID is looked up in the account's zones (Zone
1252
+ * Read). Oldest first. The board's alert webhook reports the same alerts as they fire; the store keeps one of each, and
1253
+ * one of each account-wide alert across the provider's environments.
1242
1254
  * @param {ProviderContext} ctx
1243
1255
  * @param {string} since ISO 8601
1244
1256
  * @returns {Promise<import('./infra-provider.js').Signal[]>}
@@ -1283,7 +1295,7 @@ export async function events(ctx, since) {
1283
1295
  if (!at || Date.parse(at) < from) continue;
1284
1296
  if (!fields.worker && !fields.zone && !fields.hostname && fields.zoneId)
1285
1297
  fields.zone = await zoneName(fields.zoneId);
1286
- const place = alertPlace(fields, resources);
1298
+ const place = alertPlace(fields, resources, ctx.elsewhere);
1287
1299
  if (!place) continue;
1288
1300
  signals.push({
1289
1301
  source: 'cloudflare',
@@ -143,6 +143,8 @@ export const COST_NOTE_MAX = 500;
143
143
  * @property {typeof fetch} [fetch] the fetch to call the platform with; tests pass a mock
144
144
  * @property {Resource[]} [resources] what `discover` just found in the environment's scope: the store passes it to
145
145
  * `observe` and `cost` so they needn't discover again
146
+ * @property {Resource[]} [elsewhere] what `discover` just found in the provider's other environments: `events` keeps an
147
+ * alert on a zone or hostname none of them, nor this one, uses as account-wide instead of leaving it out (BRK-256)
146
148
  * @property {Set<string>} [reached] the store's collector: the provider adds a permission's name when a call answers
147
149
  * with it, so Connections puts back one an earlier refusal struck (BRK-254)
148
150
  */