@fourier-labs/harbour 0.1.41 → 0.1.42

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.
@@ -195,7 +195,7 @@ The person you are working with may not be a developer. They say what they want
195
195
  - "run it", "show me", "let me try it" → start \`harbour dev --app-root .\` in the background (it keeps running; the first start downloads the native runtime and takes a minute or two). Wait for the line \`Harbour dev is running: http://127.0.0.1:<port>\` and give them that link. Do this unasked as soon as the first check is green — they should always have the link. Locally they are a fixture user; no company sign-in is needed.
196
196
  - "check it", "is it ok?", "is it ready?" → with dev running, \`harbour check --app-root . --json\`, then read \`.harbour/local/check-report.json\`. Failures in the app's code are yours to fix — fix, then check again until it is clean. Run the checks yourself after every change and before every ship, without being asked and without offering them as a choice.
197
197
  - "does it work?", and before you report anything as working → open the dev link in your own browser when you have one, press the control you built or changed, and read what the app shows. A green \`harbour check\` is not that proof: it answers governed AI and company systems from fixtures, so the refusals that matter (a field the company's AI route does not accept, a consent the operation does not need, a channel that is not approved) appear only when the control is really pressed. Test rendering, navigation, fixtures and approved reads automatically. In development a Send sends a real email or Slack message: reuse explicit authorization for that bounded test, or ask once if none exists; IT access approval alone is not permission to send. Never ask again for the same authorized test. Before a real integration test, run \`harbour integrations status --app-root . --json\`; explain pending IT approval or missing personal consent before pressing Send, and test the ready parts independently. If you have no browser, say that the button itself is untested.
198
- - "I need Slack / Gmail / the warehouse / company data" → a fresh \`harbour init\` declares no connection at all, which is why a new app ships with nothing waiting on IT. Never guess a connection, channel, view or mailbox name — a guessed one is refused before IT's queue ever sees it, so nothing appears for IT to approve; use the exact names the person or IT gave you, and if you have none, that is the one question to ask before declaring anything. Before asking, run \`harbour integrations catalog --app-root . --json\` it lists the company's connections by the exact identifier \`.harbour/integrations.json\` uses, the operations IT allows on each and the approved channels, views and mailboxes per environment and declare only identifiers and approved names it lists. Declare the connection and only the operations the app really calls in \`.harbour/integrations.json\` (the closed set is in the per-app block), then \`harbour integrations request <connection> --reason "<what the app does with it>" --app-root . --json\`. Request the preview grant in the same turn (\`--environment preview\`) so shipping does not wait on a second IT decision. READY means use it now. PENDING means IT has to approve it: say "IT has to approve this; the app works without it until then", and check later with \`harbour integrations status --app-root . --json\`. A refusal with \`RESOURCE_NOT_APPROVED\` means the channel, view or mailbox is not on the connection yet: IT adds it in the Harbour console under Controls & integrations → API integrations → the provider tile → Configure → Channels (a warehouse view: Controls & integrations → Databases → the source → Views for the environment), and then you run the same request command again. Say "IT has to add <name> to the Slack connection first; the app works without it until then" and nothing more. Never declare a connection the app does not call — every declared one blocks shipping until IT approves it.
198
+ - "I need Slack / Gmail / the warehouse / company data" → a fresh \`harbour init\` declares no connection at all, which is why a new app ships with nothing waiting on IT. Never guess a connection, channel, table, view, mailbox or warehouse column — a guessed name is refused before IT's queue ever sees it. Run \`harbour integrations catalog --app-root . --json\` first and use only what it lists. A warehouse resource whose catalog columns are \`["*"]\` is declared and read with \`["*"]\`; do not invent a friendlier schema or ask the person to get IT to confirm one. Declare only connections and operations the app really calls, then submit both development and preview requests yourself in the same turn with \`harbour integrations request <connection> --reason "<what the app does with it>" --app-root . --json\` and the same command with \`--environment preview\`. Never tell the person to ask IT before you have submitted the request. READY means use it now. PENDING means IT has to approve it: say "IT has to approve this; the app works without it until then", and check later with \`harbour integrations status --app-root . --json\`. A refusal with \`RESOURCE_NOT_APPROVED\` means the named resource is not on the connection yet: IT adds it in the Harbour console under Controls & integrations, and then you run the same request again. Never declare a connection the app does not call — every declared one blocks shipping until IT approves it.
199
199
  - "summarise", "draft", "explain", "AI" → one \`harbour.ai.chat\` call (through \`ai()\` in \`src/harbour.client.ts\`) behind a control the person presses; never an OpenAI/Anthropic key, SDK or URL. \`harbour check\` writes its journey. Send \`messages\` and \`maxTokens\` and nothing else: a refusal with \`unsupported_request_capability\` names a field the company's AI route does not accept — remove that field. A refusal with \`AI_NOT_ENABLED\` means IT has to enable an AI provider: say so in one line and keep the app working without it.
200
200
  - "ship it", "put it online", "let my team try it" → run \`harbour check --app-root . --json\` first and fix everything it finds, every time, unasked: the same gates run again in the cloud, where each failed attempt costs minutes instead of the seconds it costs here. Then each declared connection needs a preview grant (\`harbour integrations request <connection> --environment preview --reason "…" --app-root . --json\`); when the app calls governed AI, \`productionise\` also asks whether the company's AI setup is ready and refuses with \`AI_NOT_READY\` and the one IT step — say that line and nothing more; the app works without AI until then. \`harbour productionise --app-root . --wait --json\` gives them \`result.deployment.protectedUrl\`: a private preview that they, and the people they name, open after company sign-in. If your tool cuts the command off before it finishes, \`${continueCommand("<ref>")}\` continues the same deployment — never start another one to find out what happened. For kit apps, describe \`TRANSFORMING\` as building and checking the app; it does not mean a transformation AI is running. The CLI saves \`operationRef\` in \`.harbour/local/productionise.json\`; repeating \`productionise\` continues that operation. Keep \`operationRef\`; \`harbour setup --operation <ref> --json\` lists what is still missing (name, audience, secrets) and \`harbour profile\` / \`harbour audience\` / \`harbour secrets set\` fill it in.
201
201
  - "make it live for everyone", "go to production" → only after they have tried the preview: \`harbour promote --operation <ref> --json\` with the operation reference from productionise. Report the production link, or that an operator approval is pending.
@@ -79,7 +79,7 @@ const usage = [
79
79
  " harbour jobs run <name> --app-root <path> [--scheduled-at <UTC>] [--json] run one scheduled job now against the local services",
80
80
  " harbour integrations request <connection> --reason <text> --app-root <path> [--environment <env>] [--operations a,b] [--expires-at <UTC>] [--json]",
81
81
  " harbour integrations status --app-root <path> [--json]",
82
- " harbour integrations catalog --app-root <path> [--json] the company's connections as .harbour/integrations.json names them: identifiers, allowed operations, approved channels/views/mailboxes per environment (no app needed)",
82
+ " harbour integrations catalog --app-root <path> [--json] the company's connections as .harbour/integrations.json names them: identifiers, allowed operations, approved channels/tables/views/mailboxes per environment (no app needed)",
83
83
  "Run `harbour connect <work-email-or-start-url>` once, then sign in when Harbour asks.",
84
84
  "productionise saves the app, follows its deployment, and prints the protected preview link; promote sends a tested preview to production.",
85
85
  `--max-wait bounds how long productionise, status --wait, retry and promote follow the deployment (default 30 minutes). When it passes the command exits 0 with status RUNNING, the last known deployment state, and the \`${continueCommand("<reference>")}\` that continues the same deployment: a bounded wait is not a failure and never means start another one.`,
@@ -108,7 +108,7 @@ export async function requestIntegrations(root, client, tenantId, bundle, option
108
108
  }
109
109
  const UNREGISTERED_RESOURCE = /^resource "([^"]+)" is not registered for \S+ on "([^"]+)"$/;
110
110
  /**
111
- * Governance refuses a request that names a channel, view or mailbox IT has not
111
+ * Governance refuses a request that names a channel, table, view or mailbox IT has not
112
112
  * registered on the connection (404 RESOURCE_NOT_APPROVED) before the Review
113
113
  * queue ever sees it, so a builder cannot self-serve it. Observed: an agent
114
114
  * read the raw refusal and told the person to email an administrator, who gave
@@ -126,7 +126,7 @@ export function unregisteredResourceGuidance(error, declaration, connection, env
126
126
  const operations = Object.keys(declared?.operations ?? {});
127
127
  const provider = operations.some(name => name.startsWith("gmail.")) ? "Gmail" : operations.some(name => name.startsWith("slack.")) ? "Slack" : connection;
128
128
  const place = declared?.kind === "database"
129
- ? `Controls & integrations → Databases → ${connection} → Views for ${environment}`
129
+ ? `Controls & integrations → Databases → ${connection} → Data resources for ${environment}`
130
130
  : `Controls & integrations → API integrations → ${provider} → Configure → ${provider === "Gmail" ? "the mailbox" : "Channels"}`;
131
131
  const command = `harbour integrations request ${connection} --reason "${reason}" --app-root ${root}${environment === "development" ? "" : ` --environment ${environment}`}`;
132
132
  return new CliError(error.code, `IT has to add ${resource} to the ${connection} connection first (in the Harbour console: ${place}); the app works without it until then, and once it is added run \`${command}\` again.`, error.operationRef);
@@ -225,7 +225,7 @@ export function requestScope(declaration, connection, only) {
225
225
  ...(identityMode === "app" && entry.operations.includes("slack.message.post") && declared.presentation ? { presentation: declared.presentation } : {})
226
226
  }));
227
227
  }
228
- /** Where connection, channel, view and mailbox names come from, so an agent never guesses one (2026-09-12: six of nineteen turns spent on refused guesses). */
228
+ /** Where connection, channel, table, view and mailbox names come from, so an agent never guesses one (2026-09-12: six of nineteen turns spent on refused guesses). */
229
229
  export async function integrationsCatalog(client) {
230
230
  const listed = await client.catalog();
231
231
  return { connections: listed.connections.map(entry => ({
@@ -1,28 +1,28 @@
1
1
  export const PUBLISHED_KIT_BUNDLE = {
2
2
  "schema": "harbour.kit-bundle/1.0",
3
- "kitVersion": "0.1.40",
3
+ "kitVersion": "0.1.42",
4
4
  "sdk": {
5
5
  "package": "@harbour/app-sdk",
6
- "version": "1.1.1",
7
- "tarballSha256": "f499af191dd5a42a41e314cf93b0c7d957e0e1987cbdfc96e7c53eee06d86d25",
8
- "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:f499af191dd5a42a41e314cf93b0c7d957e0e1987cbdfc96e7c53eee06d86d25"
6
+ "version": "1.1.2",
7
+ "tarballSha256": "aa6dd568b8580ef239c32b7470e79681a54363ce7808f687e389697ef8f56d94",
8
+ "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:aa6dd568b8580ef239c32b7470e79681a54363ce7808f687e389697ef8f56d94"
9
9
  },
10
10
  "images": {
11
- "appGateway": "public.ecr.aws/y6t4p3i8/harbour-app-gateway@sha256:abaed52c0de3469bc64a21f7c542b206333fc6185d3624b5e045568dae877c27",
12
- "sessionFixture": "public.ecr.aws/y6t4p3i8/harbour-session-fixture@sha256:8efcd7ce5ce78c047a2c526d3de76e00cae01ecb55eab5f060a74a33b8650e9a"
11
+ "appGateway": "public.ecr.aws/y6t4p3i8/harbour-app-gateway@sha256:771d71975a503214fa63f94534c77483f06797f8089d7fdc027ca30e26983039",
12
+ "sessionFixture": "public.ecr.aws/y6t4p3i8/harbour-session-fixture@sha256:c3c84639da9d98c08009bacaf4017ad597bc5528acda4cee9ad0917cee35afdb"
13
13
  },
14
14
  "nativeRuntime": {
15
15
  "darwinArm64": {
16
- "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:5f40b4de50ce81abcb5ee22aa8a984b46d5a5fc719f0eee035ae6bfb3dbf47cd",
17
- "sha256": "5f40b4de50ce81abcb5ee22aa8a984b46d5a5fc719f0eee035ae6bfb3dbf47cd"
16
+ "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:2e83e6dd8747859ffabb6a832a759e95fc68aad9b374c0e16007da84aca49580",
17
+ "sha256": "2e83e6dd8747859ffabb6a832a759e95fc68aad9b374c0e16007da84aca49580"
18
18
  },
19
19
  "linuxX64": {
20
- "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:163a54cdab03f193499a35dc4821e10ae9a40c80aeec9c12005b2959f50cc01b",
21
- "sha256": "163a54cdab03f193499a35dc4821e10ae9a40c80aeec9c12005b2959f50cc01b"
20
+ "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:02ce306b179db95c16e1d3cedf6ad01d8dfba5810a2df14a03dcd2fd024478ef",
21
+ "sha256": "02ce306b179db95c16e1d3cedf6ad01d8dfba5810a2df14a03dcd2fd024478ef"
22
22
  },
23
23
  "windowsX64": {
24
- "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:1c26d2066be2e673cba0c335fee8b1057fa314ed85325e406903f3e6f9e18351",
25
- "sha256": "1c26d2066be2e673cba0c335fee8b1057fa314ed85325e406903f3e6f9e18351"
24
+ "url": "https://public.ecr.aws/v2/y6t4p3i8/harbour-kit-bundle/blobs/sha256:2cee6b4521cd7a6d6bcf7b4806e18ac26ada150f13bf45dfda06346a96a47d75",
25
+ "sha256": "2cee6b4521cd7a6d6bcf7b4806e18ac26ada150f13bf45dfda06346a96a47d75"
26
26
  }
27
27
  },
28
28
  "brief": {
@@ -1 +1 @@
1
- export const CLI_VERSION = "0.1.41";
1
+ export const CLI_VERSION = "0.1.42";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fourier-labs/harbour",
3
- "version": "0.1.41",
3
+ "version": "0.1.42",
4
4
  "description": "Harbour productionisation helper",
5
5
  "type": "module",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "harbour": {
38
38
  "kitBundle": {
39
39
  "repository": "public.ecr.aws/y6t4p3i8/harbour-kit-bundle",
40
- "version": "0.1.40"
40
+ "version": "0.1.42"
41
41
  }
42
42
  }
43
43
  }