@fourier-labs/harbour 0.1.19 → 0.1.20
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.
|
@@ -125,7 +125,10 @@ function kitFiles() {
|
|
|
125
125
|
}
|
|
126
126
|
}, null, 2)}\n`,
|
|
127
127
|
"migrations/0001_notes.sql": MIGRATION,
|
|
128
|
-
|
|
128
|
+
// One retained check per capability the starter's UI uses: the pipeline's
|
|
129
|
+
// flow gate refuses an app whose checks never exercise a declared capability.
|
|
130
|
+
".harbour/checks/notes-journey.mjs": JOURNEY_CHECK,
|
|
131
|
+
".harbour/checks/files-journey.mjs": FILES_JOURNEY_CHECK
|
|
129
132
|
};
|
|
130
133
|
}
|
|
131
134
|
function starterFiles(bundle) {
|
|
@@ -147,7 +150,7 @@ function starterFiles(bundle) {
|
|
|
147
150
|
"src/harbour.client.ts": HARBOUR_CLIENT,
|
|
148
151
|
"src/App.tsx": APP,
|
|
149
152
|
"src/SlackPanel.tsx": SLACK_PANEL,
|
|
150
|
-
"README.md": "# Harbour app\n\nCreated by `harbour init`. Run `harbour dev --app-root .` and open the printed origin. See CLAUDE.md / AGENTS.md for the kit rules.\n\n`.harbour/integrations.json` declares `company-slack` only. Declare a connection only when the app calls it: `harbour productionise` refuses to deploy until every declared connection has a preview grant (`harbour integrations request <connection> --environment preview --reason \"<why>\" --app-root .`). The warehouse example (`sales-warehouse` / `warehouse.view.read`) is in a comment in `src/App.tsx`.\n"
|
|
153
|
+
"README.md": "# Harbour app\n\nCreated by `harbour init`. Run `harbour dev --app-root .` and open the printed origin. See CLAUDE.md / AGENTS.md for the kit rules.\n\n`.harbour/checks/` holds one journey per capability the app uses (`notes-journey.mjs` for data, `files-journey.mjs` for files); `harbour check` and the deployment pipeline refuse an app whose checks never exercise an operation its own code performs, so a new feature needs its own retained check.\n\n`.harbour/integrations.json` declares `company-slack` only. Declare a connection only when the app calls it: `harbour productionise` refuses to deploy until every declared connection has a preview grant (`harbour integrations request <connection> --environment preview --reason \"<why>\" --app-root .`). The warehouse example (`sales-warehouse` / `warehouse.view.read`) is in a comment in `src/App.tsx`.\n"
|
|
151
154
|
};
|
|
152
155
|
}
|
|
153
156
|
const VITE_CONFIG = `import { defineConfig } from "vite";
|
|
@@ -388,3 +391,27 @@ await harbour.data.from("notes").delete().eq("id", notes[0].id);
|
|
|
388
391
|
const { data: remaining } = await harbour.data.from("notes").select("id").eq("title", title);
|
|
389
392
|
assert.equal(remaining.length, 0, "the note is deleted");
|
|
390
393
|
`;
|
|
394
|
+
const FILES_JOURNEY_CHECK = `// Journey check: the signed-in identity can upload a private file and list it back
|
|
395
|
+
// through the running app (HARBOUR_APP_URL) — the two operations the "Private
|
|
396
|
+
// files" section of src/App.tsx performs (\`harbour.files.upload\` / \`harbour.files.list\`).
|
|
397
|
+
// The deployment pipeline refuses an app whose checks never exercise a capability
|
|
398
|
+
// its own code uses, so this runs under \`harbour check\` while \`harbour dev\` is up,
|
|
399
|
+
// and in the pipeline's retained-check container.
|
|
400
|
+
import assert from "node:assert/strict";
|
|
401
|
+
|
|
402
|
+
const appUrl = process.env.HARBOUR_APP_URL;
|
|
403
|
+
assert.ok(appUrl, "HARBOUR_APP_URL is required");
|
|
404
|
+
const sdk = await import(process.env.HARBOUR_SDK_MODULE ?? "@harbour/app-sdk");
|
|
405
|
+
const token = process.env.HARBOUR_IDENTITY_CONTEXT_TOKEN;
|
|
406
|
+
const fetchWithIdentity = (input, init = {}) => fetch(input, { ...init, headers: { ...(init.headers ?? {}), ...(token ? { "x-harbour-identity-context": token } : {}) } });
|
|
407
|
+
const harbour = sdk.createClient({ baseUrl: appUrl, fetch: fetchWithIdentity });
|
|
408
|
+
|
|
409
|
+
const user = await harbour.identity.current();
|
|
410
|
+
assert.ok(user && user.email, "identity/current must return the signed-in user");
|
|
411
|
+
const name = \`journey-\${Date.now()}.txt\`;
|
|
412
|
+
await harbour.files.upload(\`private/\${name}\`, new Blob(["harbour journey check\\n"], { type: "text/plain" }));
|
|
413
|
+
const listed = await harbour.files.list("private/");
|
|
414
|
+
assert.ok(Array.isArray(listed), "files.list must return a list");
|
|
415
|
+
const found = listed.some(entry => String(typeof entry === "string" ? entry : entry?.path ?? entry?.name ?? "").endsWith(name));
|
|
416
|
+
assert.ok(found, \`the uploaded file is listed back to its owner (looking for \${name})\`);
|
|
417
|
+
`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export const CLI_VERSION = "0.1.
|
|
1
|
+
export const CLI_VERSION = "0.1.20";
|