@aifabrix/builder 2.59.0 → 2.60.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 (55) hide show
  1. package/lib/agent-kit/git-identity.js +180 -0
  2. package/lib/agent-kit/setup.js +3 -0
  3. package/lib/agent-kit/start.js +45 -1
  4. package/lib/api/role-assistant-test-job.api.js +60 -0
  5. package/lib/api/work-search.api.js +13 -6
  6. package/lib/app/deploy.js +8 -1
  7. package/lib/app/show-display.js +1 -0
  8. package/lib/app/show-online.js +15 -0
  9. package/lib/build/standard-docker-build.js +4 -1
  10. package/lib/cli/setup-app.js +14 -1
  11. package/lib/cli/setup-utility.js +24 -1
  12. package/lib/commands/role-assistant.js +7 -0
  13. package/lib/core/env-platform-expand.js +93 -0
  14. package/lib/core/secrets-env-content.js +37 -3
  15. package/lib/deployment/installation/azure-infra-stage.js +3 -1
  16. package/lib/deployment/installation/infra-catalog.js +2 -5
  17. package/lib/generator/builders.js +17 -0
  18. package/lib/generator/helpers.js +23 -2
  19. package/lib/generator/index.js +10 -6
  20. package/lib/role-assistant/test-cases-search.js +3 -0
  21. package/lib/role-assistant/test-job-runner.js +125 -0
  22. package/lib/role-assistant/test-runner-search.js +44 -2
  23. package/lib/schema/application-schema.json +193 -2
  24. package/lib/schema/infra-parameter.schema.json +139 -33
  25. package/lib/schema/infra.parameter.yaml +28 -28
  26. package/lib/schema/infrastructure-schema.json +10 -35
  27. package/lib/utils/compose-generate-docker-compose.js +12 -0
  28. package/lib/utils/docker-build.js +29 -8
  29. package/lib/utils/docker-manifest-public-port.js +36 -0
  30. package/lib/utils/platform-resolution.js +226 -0
  31. package/lib/utils/resolve-docker-image-ref.js +8 -3
  32. package/package.json +2 -2
  33. package/templates/README.md +2 -1
  34. package/templates/agent-kit/agent-kit.yaml +4 -1
  35. package/templates/agent-kit/instructions/AGENTKIT.md +1 -1
  36. package/templates/agent-kit/instructions/root.AGENTS.md +2 -0
  37. package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +33 -1
  38. package/templates/agent-kit/skills/aifabrix-connected-system/scripts/delivery-verdict.js +176 -0
  39. package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +3 -0
  40. package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +10 -3
  41. package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +22 -0
  42. package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +21 -0
  43. package/templates/agent-kit/skills/shared/feedback.md +31 -0
  44. package/templates/agent-kit/skills/shared/hosts.md +13 -3
  45. package/templates/agent-kit/skills/shared/status.md +85 -0
  46. package/templates/agent-kit/workspace/BUILDER_IMPROVEMENT_FINDINGS.md +27 -0
  47. package/templates/applications/builder-api/application.yaml +1 -1
  48. package/templates/applications/dataplane/application.yaml +30 -2
  49. package/templates/applications/dataplane/env.template +37 -4
  50. package/templates/applications/miso-controller/application.yaml +24 -1
  51. package/templates/applications/miso-controller/env.template +21 -34
  52. package/templates/marketplace/main.json +70 -222
  53. package/templates/python/Dockerfile.hbs +2 -0
  54. package/templates/typescript/Dockerfile.hbs +2 -0
  55. package/templates/typescript/docker-compose.hbs +12 -0
@@ -0,0 +1,176 @@
1
+ /**
2
+ * Delivery verdict for a customer Connected System and Role Assistant.
3
+ *
4
+ * The agent records what it observed; this decides the verdict. Keeping the decision here
5
+ * rather than in skill prose means a passing package cannot be narrated into a passing
6
+ * delivery: precedence is computed, not chosen.
7
+ *
8
+ * Gates are reported separately on purpose. A package can be BUILT while the delivery
9
+ * needs fixes and prove is blocked, and all three are true at once.
10
+ *
11
+ * @fileoverview Deterministic status matrix and overall verdict for customer delivery skills
12
+ */
13
+
14
+ 'use strict';
15
+
16
+ /** Worst-first. A later gate never improves an earlier one. */
17
+ const RANK = ['BLOCKED', 'NEEDS_FIXES', 'PASS_WITH_SKIPS', 'PASS'];
18
+ const UNKNOWN = 'UNKNOWN';
19
+
20
+ /**
21
+ * @param {string} a First verdict
22
+ * @param {string} b Second verdict
23
+ * @returns {string} The worse of the two
24
+ */
25
+ function worse(a, b) {
26
+ const left = RANK.indexOf(a);
27
+ const right = RANK.indexOf(b);
28
+ if (left < 0) return b;
29
+ if (right < 0) return a;
30
+ return left <= right ? a : b;
31
+ }
32
+
33
+ /**
34
+ * Trim and uppercase an observed field. Missing values become an empty string.
35
+ * @param {*} value Observed field
36
+ * @returns {string} Normalized token
37
+ */
38
+ function norm(value) {
39
+ return String(value === undefined || value === null ? '' : value).trim().toUpperCase();
40
+ }
41
+
42
+ /**
43
+ * Published is the only online state that permits publish completion or live prove.
44
+ * @param {object} signals Observed signals
45
+ * @returns {{ state: string, published: boolean, known: boolean }} Online state
46
+ */
47
+ function onlineState(signals) {
48
+ const state = norm(signals.onlineState) || UNKNOWN;
49
+ return {
50
+ state,
51
+ published: state === 'PUBLISHED',
52
+ known: state === 'PUBLISHED' || state === 'DRAFT'
53
+ };
54
+ }
55
+
56
+ /**
57
+ * Builder's pillar verdicts are VERIFIED, FAILED, NOT_VERIFIED and NOT_APPLICABLE
58
+ * (`lib/lifecycle/product-model.js`). NOT_VERIFIED is not a pass — it is the state a pillar
59
+ * sits in until it has actually been proved, and treating it as neutral is how an
60
+ * unverified system gets reported as delivered. A gate that was never run is UNKNOWN.
61
+ * @param {object} gate Observed gate result
62
+ * @returns {string} Normalized verdict
63
+ */
64
+ function gateVerdict(gate) {
65
+ if (!gate) return UNKNOWN;
66
+ const verdict = norm(gate.verdict);
67
+ if (!verdict || verdict === 'NOT_RUN' || verdict === 'SKIPPED') return UNKNOWN;
68
+ if (verdict === 'VERIFIED' || verdict === 'PASSED' || verdict === 'PASS') return 'PASS';
69
+ if (verdict === 'NOT_APPLICABLE') return 'PASS';
70
+ if (verdict === 'FAILED' || verdict === 'FAIL' || verdict === 'NOT_VERIFIED') return 'NEEDS_FIXES';
71
+ return 'NEEDS_FIXES';
72
+ }
73
+
74
+ /**
75
+ * Failures stay active until the same concern is rerun and passes, so a later structural
76
+ * success cannot clear an earlier runtime, governance, persistence, or E2E failure.
77
+ * @param {Array} knownFailures Recorded failures
78
+ * @returns {Array} Failures still open
79
+ */
80
+ function openFailures(knownFailures) {
81
+ const rows = Array.isArray(knownFailures) ? knownFailures : [];
82
+ return rows.filter(row => row && row.resolved !== true && norm(row.resolved) !== 'TRUE');
83
+ }
84
+
85
+ /**
86
+ * One status-matrix cell: verdict plus an optional percent.
87
+ * @param {object} gate Observed gate result
88
+ * @returns {string} Display text
89
+ */
90
+ function describeScore(gate) {
91
+ if (!gate) return UNKNOWN;
92
+ const verdict = norm(gate.verdict) || norm(gate.category) || UNKNOWN;
93
+ const percent = gate.percent === undefined || gate.percent === null ? '' : ` ${gate.percent}%`;
94
+ return `${verdict}${percent}`;
95
+ }
96
+
97
+ /**
98
+ * Overall delivery verdict. PASS needs a published system and acceptable Operations,
99
+ * Trust, Governance and live-evidence results; an unrun gate is not a pass. BLOCKED is
100
+ * reserved for a delivery that cannot be assessed or was explicitly stopped — a draft
101
+ * system is fixable work, so it reports NEEDS_FIXES.
102
+ * @param {object} signals Observed signals
103
+ * @returns {string} BLOCKED | NEEDS_FIXES | PASS_WITH_SKIPS | PASS
104
+ */
105
+ function overallVerdict(signals) {
106
+ const online = onlineState(signals);
107
+ if (!online.known || signals.blocked === true) return 'BLOCKED';
108
+ let verdict = online.published ? 'PASS' : 'NEEDS_FIXES';
109
+ for (const gate of [signals.operations, signals.trust, signals.governance, signals.liveEvidence]) {
110
+ const result = gateVerdict(gate);
111
+ verdict = worse(verdict, result === UNKNOWN ? 'NEEDS_FIXES' : result);
112
+ }
113
+ if (openFailures(signals.knownFailures).length > 0) verdict = worse(verdict, 'NEEDS_FIXES');
114
+ const skips = Array.isArray(signals.allowedSkips) ? signals.allowedSkips : [];
115
+ if (verdict === 'PASS' && skips.length > 0) return 'PASS_WITH_SKIPS';
116
+ return verdict;
117
+ }
118
+
119
+ /**
120
+ * Prove readiness is a business-case gate. Package validation, pipeline checks, a Bronze
121
+ * certification or TECHNICALLY_READY never establish it on their own.
122
+ * @param {object} signals Observed signals
123
+ * @returns {string} READY | BLOCKED
124
+ */
125
+ function proveReadiness(signals) {
126
+ const overall = overallVerdict(signals);
127
+ if (overall !== 'PASS' && overall !== 'PASS_WITH_SKIPS') return 'BLOCKED';
128
+ const ra = signals.roleAssistant || {};
129
+ // `role-assistant test --json` gives the verdict. Availability is an operator action with
130
+ // no CLI surface, so it must be confirmed explicitly; unconfirmed is not available.
131
+ if (gateVerdict(ra) !== 'PASS' || norm(ra.availability) !== 'AVAILABLE') return 'BLOCKED';
132
+ const cases = signals.cases || {};
133
+ if (cases.happy !== true || cases.safeStop !== true) return 'BLOCKED';
134
+ if (signals.authorityConfirmed !== true) return 'BLOCKED';
135
+ return 'READY';
136
+ }
137
+
138
+ /**
139
+ * Every row the skills must report, in a fixed order.
140
+ * @param {object} signals Observed signals
141
+ * @returns {Array<{ gate: string, value: string }>} Status matrix rows
142
+ */
143
+ function statusMatrix(signals) {
144
+ const ra = signals.roleAssistant || {};
145
+ const availability = `${norm(ra.availability) || UNKNOWN}/${norm(ra.verdict) || UNKNOWN}`;
146
+ return [
147
+ { gate: 'Package', value: norm(signals.packageGate) || UNKNOWN },
148
+ { gate: 'Online', value: onlineState(signals).state },
149
+ { gate: 'AI Readiness', value: describeScore(signals.aiReadiness) },
150
+ { gate: 'Operations', value: describeScore(signals.operations) },
151
+ { gate: 'Trust', value: describeScore(signals.trust) },
152
+ { gate: 'Governance', value: describeScore(signals.governance) },
153
+ { gate: 'Role Assistant', value: availability },
154
+ { gate: 'Prove readiness', value: proveReadiness(signals) },
155
+ { gate: 'Delivery', value: overallVerdict(signals) }
156
+ ];
157
+ }
158
+
159
+ /**
160
+ * A headline may not claim success the overall verdict does not support.
161
+ * @param {object} signals Observed signals
162
+ * @returns {boolean} True when a bare READY, BUILT or PASS headline is forbidden
163
+ */
164
+ function forbidsSuccessHeadline(signals) {
165
+ const overall = overallVerdict(signals);
166
+ return overall === 'BLOCKED' || overall === 'NEEDS_FIXES';
167
+ }
168
+
169
+ module.exports = {
170
+ worse,
171
+ statusMatrix,
172
+ overallVerdict,
173
+ proveReadiness,
174
+ openFailures,
175
+ forbidsSuccessHeadline
176
+ };
@@ -12,6 +12,9 @@ description: >
12
12
  Input: business specification and optional `systemKey`.
13
13
  Output: one delivery plan from [plan-template.md](references/plan-template.md).
14
14
 
15
+ Named with no specification, report what exists and ask; do not start writing a plan from
16
+ an inferred spec ([status.md](../shared/status.md)).
17
+
15
18
  Score completeness with [challenge-checklist.md](references/challenge-checklist.md).
16
19
  Next-step interaction: [interaction.md](references/interaction.md).
17
20
  Host runtimes (local vs SSH): [hosts.md](../shared/hosts.md).
@@ -24,11 +24,18 @@ Archive is a distinct user decision (`archive-yes` / `archive-no`). Never archiv
24
24
  - NEEDS_DECISIONS: AskQuestion challenge rows. No `cust-next`.
25
25
  - BLOCKED / FAIL / NEEDS_FIXES / ABORTED: do not offer the next phase as if success.
26
26
 
27
+ A phase gate is per-gate, not overall. Offer the next phase only when the **Delivery** row
28
+ supports it; a passing package gate beside `Delivery: NEEDS_FIXES` is not success and the
29
+ offer must name what is still open.
30
+
27
31
  ## Phase detection (connected-system and prove)
28
32
 
29
33
  1. Explicit phase from the user
30
- 2. Active plan and package state
31
- 3. Safe next eligible phase
32
- 4. Ask once if ambiguous
34
+ 2. Ask, offering the routes in [status.md](../../shared/status.md)
35
+
36
+ There is no third step. Package and plan state decide what you *recommend*, never what you
37
+ run: a bare invocation reports status and stops ([status.md](../../shared/status.md)).
38
+ Inferring "the safe next eligible phase" is what makes a skill start working before the
39
+ user has said what they want.
33
40
 
34
41
  Never silently run the following phase after success.
@@ -12,8 +12,30 @@ description: >
12
12
  Phases: `validate` | `build` | `prove`.
13
13
  Loop: validate ↔ build ↔ prove ↔ learn.
14
14
 
15
+ **No phase argument means run prove-readiness validation only.** Report the combined status
16
+ matrix and the readiness verdict, recommend one next phase, and stop. Do not build proof
17
+ assets, run cases, publish, or promote: [status.md](../shared/status.md).
18
+
15
19
  `READY` means prove-ready, not permission to stop authoring. Build may run without READY.
16
20
 
21
+ ## Prove readiness
22
+
23
+ READY requires **all** of:
24
+
25
+ - Connected System PASS, or PASS_WITH_SKIPS whose skips the user allowed by name
26
+ - online state Published
27
+ - Operations not failed
28
+ - relevant governance scenarios passed
29
+ - Role Assistant available and verified
30
+ - happy and safe-stop cases present for the scenarios in scope
31
+ - authority, test subjects, and required business inputs confirmed
32
+
33
+ Anything short of all of them is BLOCKED, reported with the row that blocks it.
34
+ [delivery-verdict.js](../aifabrix-connected-system/scripts/delivery-verdict.js) computes it.
35
+
36
+ Package validation, pipeline checks, Bronze certification and TECHNICALLY_READY are **not**
37
+ business-case readiness. None of them, alone or together, makes prove READY.
38
+
17
39
  Every phase **must** update [learning-template.md](references/learning-template.md).
18
40
  Evidence rules: [evidence-lifecycle.md](references/evidence-lifecycle.md).
19
41
  Demo shape: [demo-template.md](references/demo-template.md).
@@ -12,6 +12,8 @@ See [package-boundary.md](references/package-boundary.md) and nested `role-assis
12
12
  Host runtimes (local vs SSH): [hosts.md](../shared/hosts.md).
13
13
  CLI login from chat: [login.md](../shared/login.md).
14
14
 
15
+ Named with no task, report status and stop: [status.md](../shared/status.md).
16
+
15
17
  ## Preconditions
16
18
 
17
19
  ```bash
@@ -22,6 +24,25 @@ aifabrix role list --page-size 1000
22
24
  Catalog Business Role and an active user binding are prerequisites.
23
25
  Connected Systems this assistant needs must be dataplane **published** (deploy, not upload-only).
24
26
 
27
+ ## Readiness gate
28
+
29
+ Report the assistant as available and verified only when every row holds. Any missing row
30
+ means NOT_VERIFIED, named by row — never a blanket claim.
31
+
32
+ | Row | Established by |
33
+ | --- | --- |
34
+ | Active catalog role | `aifabrix role list --page-size 1000` |
35
+ | Required Connected Systems published **and** certified | `show --online` plus their Delivery verdict |
36
+ | Subscribed capabilities available | capability check against those systems |
37
+ | OpenAPI published | `role-assistant test --json` → `openApiPublished` |
38
+ | Lifecycle verified | `role-assistant test --json` → `verdict` is `VERIFIED` |
39
+ | Worker available | operator "Make available"; **no CLI surface** — confirm explicitly or report UNKNOWN |
40
+ | Happy and safe-stop cases discoverable | cases present for the scenarios in scope |
41
+
42
+ A published Connected System that is not certified does not satisfy row two. `verdict`
43
+ `NOT_VERIFIED` is not a pass, and a `certification.level` such as `BRONZE` never
44
+ substitutes for it.
45
+
25
46
  ## Workflow
26
47
 
27
48
  1. `aifabrix download <catalogRoleOrRaKey>` before editing an existing assistant.
@@ -0,0 +1,31 @@
1
+ # Feedback — where an observation goes
2
+
3
+ `aifabrix agent-kit update` rewrites `.agents/skills/**`, `AGENTKIT.md`, and the
4
+ managed sections of `AGENTS.md` and `CLAUDE.md` from the installed kit. Editing
5
+ them blocks the next update as a conflict, and `--force` discards the edit with
6
+ no diff to review. Improve the kit by filing a finding, not by editing a skill.
7
+
8
+ | Observation | Where it goes |
9
+ | --- | --- |
10
+ | Generic CLI, skill, or platform gap | `BUILDER_IMPROVEMENT_FINDINGS.md` |
11
+ | Manual EDS edit | `integration/<systemKey>/INTEGRATION_CHANGELOG.md` |
12
+ | Vendor limits, tenant ids, PII stance | `integration/<systemKey>/README.md` |
13
+ | Delivery learning for a role | `role-assistant/ra-<roleKey>/learning/learning.md` |
14
+
15
+ ## Writing a finding
16
+
17
+ Newest first, under a `## YYYY-MM-DD — one line naming the gap` heading:
18
+
19
+ - **Command** — the exact command, customer values replaced by placeholders.
20
+ - **Observed** — what happened, with the error text and the verdict.
21
+ - **Expected** — what should have happened, and why that is reasonable.
22
+ - **Scope** — whether it reproduces outside this workspace, and what is still
23
+ unproven. Say so plainly when the root cause is not established.
24
+
25
+ A finding is read outside this workspace, so leave out correlation ids, audit
26
+ refs, internal URLs, tenant or record identifiers, hostnames, and customer
27
+ names. Customer specifics belong in the package README or the role's
28
+ `learning.md` instead.
29
+
30
+ Never weaken a gate, assertion, or test to make a finding go away. A failing
31
+ gate with a filed finding is a better outcome than a green run that hides one.
@@ -18,7 +18,17 @@ permission settings; the standalone start defaults below remain separate.
18
18
  - Claude Code: `.claude/settings.local.json` (`permissions.defaultMode` = `bypassPermissions`, `allow` = `Bash(aifabrix *)` and `Read(~/**)`)
19
19
  - Codex: `.codex/config.toml` (`approval_policy = "never"`, `sandbox_mode = "workspace-write"`)
20
20
 
21
- Those files stay in **this workspace**. Claude may **read** files under the developer home (`Read(~/**)`) and run the delivery CLI (`Bash(aifabrix *)`). They do not add sibling folders as extra workspaces, do not grant Write outside this repo, and do not allow every shell command. `agent-kit start claude|codex` writes only the selected host's file by default; `--skip-approve-all` opts out. Install/update retain their explicit approval prompts and flags. `--force` overwrites existing local files. Builder never writes `~/.claude` or `~/.codex`.
21
+ Those files stay in **this workspace**; Builder never writes `~/.claude` or `~/.codex`, and neither file adds a sibling folder as an extra workspace.
22
+
23
+ Understand what you are accepting for Claude Code. `bypassPermissions` stops the
24
+ prompt for **every** tool call in this workspace, not only the two `allow`
25
+ entries, which grant nothing extra while that mode is set. That includes
26
+ `aifabrix` subcommands which change remote state, such as `deploy`, `upload`,
27
+ `identity sync` and `protection upload`. Codex is narrower: `approval_policy`
28
+ removes the prompt, while `sandbox_mode = "workspace-write"` still confines
29
+ writes to this workspace.
30
+
31
+ Use `--skip-approve-all` when you want the prompts, on a shared or production-connected installation. `agent-kit start claude|codex` writes only the selected host's file by default. Install/update retain their explicit approval prompts and flags. `--force` overwrites existing local files.
22
32
 
23
33
  ## Cursor
24
34
 
@@ -38,7 +48,7 @@ available from the same Claude account when supported.
38
48
  aifabrix agent-kit start claude
39
49
  ```
40
50
 
41
- tmux session name is this folder (for example `aifabrix-docs`). Remote Control name is `hostname-user-folder` (for example `builder01-dev03-aifabrix-docs`). `--name` overrides the folder; `--no-remote-control` and `--skip-approve-all` opt out. Several workspaces can run at once. Detach without killing Claude: `Ctrl-b` then `d`. Reattach: `tmux attach -t aifabrix-docs`. A duplicate `start` fails instead of attaching. Then `/aifabrix-plan` (or another `/aifabrix-*` skill). First run in a project asks you to trust the folder; accept only this workspace.
51
+ tmux session name is this folder (for example `acme-workspace`). Remote Control name is `hostname-user-folder` (for example `devhost-alice-acme-workspace`). `--name` overrides the folder; `--no-remote-control` and `--skip-approve-all` opt out. Several workspaces can run at once. Detach without killing Claude: `Ctrl-b` then `d`. Reattach: `tmux attach -t acme-workspace`. A duplicate `start` fails instead of attaching. Then `/aifabrix-plan` (or another `/aifabrix-*` skill). First run in a project asks you to trust the folder; accept only this workspace.
42
52
 
43
53
  **Phone and PC.** Sign in with the same Claude Pro/Max/Team account (`claude auth login` — not an API key). After Remote Control starts, open **Code** in the Claude mobile app and/or [claude.ai/code](https://claude.ai/code) on the PC. In an already-running session, `/remote-control` or `/mobile`.
44
54
 
@@ -60,7 +70,7 @@ installer.
60
70
  aifabrix agent-kit start codex
61
71
  ```
62
72
 
63
- Default `--name` is the last folder. `--no-remote-control` skips that daemon; `--skip-approve-all` leaves Codex permissions unchanged. If that session already exists, `start` fails with list/kill guidance. Detach: `Ctrl-b` then `d`. Reattach with `tmux attach -t aifabrix-docs`. Then `$aifabrix-plan` (and the other `$aifabrix-*` skills). Codex reads `AGENTS.md`. A separate Codex app server used by a desktop SSH chat appears in `agent-kit list` and the interactive `agent-kit kill` menu; stopping it requires confirmation and may disconnect the chat. `codex remote-control stop` only controls a standalone-managed daemon.
73
+ Default `--name` is the last folder. `--no-remote-control` skips that daemon; `--skip-approve-all` leaves Codex permissions unchanged. If that session already exists, `start` fails with list/kill guidance. Detach: `Ctrl-b` then `d`. Reattach with `tmux attach -t acme-workspace`. Then `$aifabrix-plan` (and the other `$aifabrix-*` skills). Codex reads `AGENTS.md`. A separate Codex app server used by a desktop SSH chat appears in `agent-kit list` and the interactive `agent-kit kill` menu; stopping it requires confirmation and may disconnect the chat. `codex remote-control stop` only controls a standalone-managed daemon.
64
74
 
65
75
  **Foreground only (no tmux).**
66
76
 
@@ -0,0 +1,85 @@
1
+ # Status first — what a bare invocation does
2
+
3
+ A skill named with no phase is a **question, not an instruction**. Report status, say what
4
+ you would do next, and wait. This is the default for every lifecycle skill.
5
+
6
+ ## Read-only means read-only
7
+
8
+ With no phase argument, you may read local packages, run `aifabrix auth status`, and run
9
+ read-only inspection such as `show --online` and `list`. You may **not**:
10
+
11
+ - upload, deploy, publish, or promote anything
12
+ - advance a plan task or mark one done
13
+ - create proof assets, Evidence, Knowledge, or tests
14
+ - run assistant cases or any command that mutates external state
15
+
16
+ Never infer a phase from "the safe next eligible one". Ambiguity is a reason to ask, not a
17
+ licence to start. Read-only inspection is still allowed when the user names a phase that
18
+ cannot run yet — report why instead of doing adjacent work.
19
+
20
+ ## Open by saying what you are about to do
21
+
22
+ Before the first command of any phase, state in one line what the phase will change and
23
+ what it will leave alone. A user who has not used this kit before cannot consent to work
24
+ they cannot see coming.
25
+
26
+ ## Offer the route, do not choose it
27
+
28
+ Ask once, with these options. Proceed only on an explicit choice.
29
+
30
+ | Option id | Means |
31
+ | --- | --- |
32
+ | `route-normal` | Run the normal path for this skill through to its gate, stopping at each phase gate |
33
+ | `route-check` | Inspect and test only — validation, checks and status, no publish or promotion |
34
+ | `route-other` | Something else; ask what |
35
+ | `next-stop` | Stop here |
36
+
37
+ `route-normal` still stops at every phase gate and still needs `next-yes` to continue
38
+ ([interaction.md](../aifabrix-plan/references/interaction.md)). It is a route, not a
39
+ licence to run the whole lifecycle unattended.
40
+
41
+ ## Always report the combined matrix
42
+
43
+ Report every row, in this order, for any status, phase result, or completion claim. Use
44
+ `UNKNOWN` for anything not measured — never omit a row and never fill one by inference.
45
+ [delivery-verdict.js](../aifabrix-connected-system/scripts/delivery-verdict.js) computes
46
+ the verdict rows from what you observed.
47
+
48
+ | Row | Where the value comes from |
49
+ | --- | --- |
50
+ | Package | `aifabrix validate <key>` — `Validation passed!` / `Validation failed!` (`--format json` gives `valid`) |
51
+ | Online | `aifabrix show <key> --online` — `Draft` / `Published` / `Archived`; `--json` returns the raw lowercase status |
52
+ | AI Readiness | **no CLI surface** — record what the portal shows, or report `UNKNOWN` |
53
+ | Operations | `aifabrix verify-operations <key> --json` — `verdict`, `operationalReadinessPercent` |
54
+ | Trust | `aifabrix verify-trust <key> --json` — `verdict`, `aiTrustPercent` |
55
+ | Governance | `aifabrix verify-governance <key> --json` — `verdict`, `policyCoveragePercent` |
56
+ | Role Assistant | `aifabrix role-assistant test <roleKey> --json` — `verdict`, `certification`. **Availability is an operator action with no CLI surface**: confirm it explicitly or report `UNKNOWN` |
57
+ | Prove readiness | computed — READY or BLOCKED |
58
+ | Delivery | computed — overall verdict |
59
+
60
+ Pillar verdicts are `VERIFIED`, `FAILED`, `NOT_VERIFIED`, `NOT_APPLICABLE` — never `PASSED`.
61
+ `NOT_VERIFIED` is **not** a pass: it is where a pillar sits until it has been proved.
62
+ Certification is a separate axis (`BRONZE`…`PLATINUM`, `TECHNICALLY_READY`…), never a
63
+ substitute for a verdict.
64
+
65
+ `READY`, `BUILT`, `PASS`, `PASS_WITH_SKIPS`, `NEEDS_FIXES` and `BLOCKED` are this kit's
66
+ delivery vocabulary, not CLI output. Never quote them as if a command printed them.
67
+
68
+ ## Never headline a success the verdict does not support
69
+
70
+ When Delivery is `NEEDS_FIXES` or `BLOCKED`, do not open with a bare `READY`, `BUILT`,
71
+ `PASS`, or "all checks passed". Qualify every claim with its scope:
72
+
73
+ ```text
74
+ Package: BUILT · Online: Draft · Operations: FAILED 60% · Delivery: NEEDS_FIXES · Prove: BLOCKED
75
+ ```
76
+
77
+ A green package gate is a statement about files on disk. It says nothing about whether the
78
+ system is published, whether it behaves correctly, or whether the business case is proven.
79
+
80
+ ## A known failure stays open
81
+
82
+ A runtime, governance, persistence, or E2E failure remains active until **that same
83
+ concern** is rerun and passes. Later structural or integration success does not clear it,
84
+ and neither does a rerun of a different layer. Carry open failures into every subsequent
85
+ status report until they are genuinely resolved.
@@ -0,0 +1,27 @@
1
+ # Builder improvement findings
2
+
3
+ Generic gaps in the Builder CLI, the Agent Kit skills, or the platform. Created
4
+ once by `aifabrix agent-kit install` and owned by this workspace from then on;
5
+ update never rewrites it.
6
+
7
+ File a finding here instead of editing `.agents/skills/**`, which
8
+ `aifabrix agent-kit update` rewrites. Never weaken a gate, assertion, or test to
9
+ make a finding go away.
10
+
11
+ Keep customer specifics out: no correlation ids, audit refs, internal URLs,
12
+ tenant or record identifiers, hostnames, or customer names. A reader outside
13
+ this workspace should still be able to act on it. Anything customer-specific
14
+ belongs in `integration/<systemKey>/README.md` or the role's `learning.md`.
15
+
16
+ Newest first.
17
+
18
+ ## YYYY-MM-DD — One line naming the gap
19
+
20
+ Command: the exact command, with customer values replaced by placeholders.
21
+
22
+ Observed: what happened, including the error text and the verdict.
23
+
24
+ Expected: what should have happened, and why that is the reasonable behavior.
25
+
26
+ Scope: whether this reproduces outside this workspace, and what is still
27
+ unproven. Say so plainly when the root cause is not established.
@@ -5,7 +5,7 @@ app:
5
5
  description: 'Business Transformation services — HTTP orchestration for connected-system workspace lifecycle via Dataplane Enterprise MCP and governance APIs.'
6
6
  type: webapp
7
7
  language: typescript
8
- version: 2.59.0
8
+ version: 2.60.0
9
9
 
10
10
  # Image Configuration
11
11
  image:
@@ -5,7 +5,7 @@ app:
5
5
  description: "AI Fabrix Dataplane is a secure, in-tenant integration and automation layer that supplies governed, normalized, and explainable enterprise data to AI agents. Using CIP as a declarative standard, it enforces RBAC and ABAC, executes integrations, and exposes trusted data via MCP and OpenAPI."
6
6
  type: webapp
7
7
  language: python # Explicitly specify Python language
8
- version: 2.0.71
8
+ version: 2.0.74
9
9
  # Image Configuration
10
10
  # Set tag to match your build (example: aifabrix build dataplane -t 1.0.0).
11
11
  # Registry is required so the controller can pull the image (avoids docker-not-found on the controller host).
@@ -98,7 +98,35 @@ build:
98
98
  # (never product OPENAI_* / AZURE_OPENAI_*). ≥2 providers →
99
99
  # ENTERPRISE_LLM_DEFAULT_SELECTOR (portal/env deploy default); Environment
100
100
  # Settings ai.llmProvider overrides without redeploy.
101
- # - ENVIRONMENT → set by deployment target
101
+ # - ENVIRONMENT → resolved per environment below
102
+
103
+ # =============================================================================
104
+ # Environment Resolution
105
+ # =============================================================================
106
+ # One installation runs dev, tst and pro Dataplanes side by side
107
+ # (environmentScopedResources: true), so these values vary by environment, not by
108
+ # resource group. There is no `platforms:` section: nothing here depends on which
109
+ # stack the installation is. env.template consumes the names as {NAME}.
110
+ environments:
111
+ - environment: dev
112
+ configuration:
113
+ - name: ENVIRONMENT
114
+ value: 'dev'
115
+ - name: PIPELINE_ENV_KEY
116
+ value: 'dev'
117
+ - environment: tst
118
+ configuration:
119
+ - name: ENVIRONMENT
120
+ value: 'tst'
121
+ - name: PIPELINE_ENV_KEY
122
+ value: 'tst'
123
+ - environment: pro
124
+ configuration:
125
+ - name: ENVIRONMENT
126
+ value: 'pro'
127
+ # Empty keeps the existing behaviour: derive the key from MISO_CLIENTID.
128
+ - name: PIPELINE_ENV_KEY
129
+ value: ''
102
130
 
103
131
  configuration:
104
132
  # -------------------------------------------------------------------------
@@ -8,8 +8,8 @@
8
8
 
9
9
  # HTTP port for the app
10
10
  PORT=${PORT}
11
- # dev | tst | pro
12
- ENVIRONMENT=dev
11
+ # dev | tst | pro. Resolved from the deployment environment; local Docker is dev.
12
+ ENVIRONMENT={ENVIRONMENT}
13
13
  # Enable debug mode
14
14
  DEBUG=false
15
15
  # Logging level: DEBUG, INFO, WARNING, ERROR, CRITICAL
@@ -44,7 +44,7 @@ API_KEY_BYPASS_ROLES=full-access
44
44
 
45
45
  # API Configuration
46
46
  API_V1_STR=/api/v1
47
- VERSION=2.0.71
47
+ VERSION=2.0.74
48
48
  # Minimum supported aifabrix-builder CLI semver (advertised on /health and /api/v1/health; empty = no gate)
49
49
  # MIN_BUILDER_CLI_VERSION=2.45.0
50
50
  MIN_BUILDER_CLI_VERSION=2.45.5
@@ -98,6 +98,15 @@ DB_3_PASSWORD=kv://databases-dataplane-3-passwordKeyVault
98
98
  # so Docker dataplane + miso-controller do not exhaust max_connections alongside make dev.
99
99
  # SAME_SERVER_POOL_BUDGET=24
100
100
 
101
+ # Transaction lifetime guardrails (587.0). Loaders run remote/AI/file work outside
102
+ # transactions; these are leak guards and telemetry, not the normal control path.
103
+ # idle_in_transaction_session_timeout applied to every Dataplane engine (seconds, 0 = off).
104
+ DB_IDLE_IN_TRANSACTION_TIMEOUT_SECONDS=60
105
+ # Warn (sanitized: loader/phase/duration/counts/correlation only) when one transaction exceeds this.
106
+ DB_SLOW_TRANSACTION_WARN_SECONDS=5
107
+ # Upper bound of rows per Evidence bulk load request (atomic below the bound; larger fails before mutation).
108
+ EVIDENCE_LOAD_MAX_ITEMS=500
109
+
101
110
  # =============================================================================
102
111
  # REDIS CONFIGURATION
103
112
  # =============================================================================
@@ -128,6 +137,21 @@ ABAC_POLICY_PARSE_CACHE_MAX_ENTRIES=2048
128
137
  # AUTHENTICATION CONFIGURATION
129
138
  # =============================================================================
130
139
 
140
+ # MISO secret runtime (583.0): every process calls miso-client init_secrets() once.
141
+ # Unset/local: MISO_AUTH_MODE=local — the SDK keeps this .env/dotenv credential flow.
142
+ # Azure: deployment supplies MISO_AUTH_MODE=azure-managed-identity, MISO_CONTROLLER_URL,
143
+ # MISO_BOOTSTRAP_AUDIENCE (and optional AZURE_CLIENT_ID); Miso-managed secrets
144
+ # (DATABASE_URL, REDIS_URL, ENCRYPTION_KEY, ...) come from the Controller broker,
145
+ # never from this file, and no MISO_CLIENTSECRET is required or returned.
146
+ # Rotation: changed names are reread from the SDK; DB/Redis pools are disposed and
147
+ # the process reports secretRotationRestartRequired until restarted. Invalidation
148
+ # (denial/expiry) stops new secret-dependent work and makes health unhealthy.
149
+ # Health: /health, /api/v1/health and /api/v1/health/platform return HTTP 503 with
150
+ # reasonCode misoTokenUnavailable | misoTokenRejected | misoControllerUnreachable |
151
+ # misoValidationTimeout whenever the Controller does not accept the live client
152
+ # token — in LOCAL_MODE too. These endpoints measure usable application health,
153
+ # not process liveness.
154
+ MISO_AUTH_MODE=local
131
155
  # MISO Application Client Credentials (per application)
132
156
  # Backend-only: never expose MISO_CLIENTSECRET to the Vite frontend (use VITE_* in app-ui).
133
157
  MISO_CLIENTID=kv://dataplane-client-idKeyVault
@@ -151,7 +175,7 @@ MISO_LOGOUT_URL=/logout
151
175
  # Environment key sent to miso-controller (e.g. environmentKey on RBAC/register) when not supplied in the payload.
152
176
  # Set MISO_PIPELINE_ENV_KEY=dev when the controller installation uses dev (e.g. MISO_CLIENTID=miso-controller-dev-dataplane).
153
177
  # If unset, derived from MISO_CLIENTID (e.g. dev from miso-controller-dev-dataplane).
154
- MISO_PIPELINE_ENV_KEY=
178
+ MISO_PIPELINE_ENV_KEY={PIPELINE_ENV_KEY}
155
179
 
156
180
  # LLM: chat/embed route through governed enterprise-llm only. Provider credentials
157
181
  # live on LLM provider external systems + dataplane secret store (not product .env).
@@ -334,3 +358,12 @@ TRUST_AI_EXPOSURE_GATE_ENABLED=false
334
358
  # when 346.rules / §17 revisions must invalidate existing certificates without matching rulesVersion.
335
359
  CERTIFICATION_DATASOURCE_SCHEMA_VERSION=
336
360
  CERTIFICATION_RULES_VERSION=
361
+
362
+ # =============================================================================
363
+ # DIMENSION ABAC ENFORCEMENT (589.0)
364
+ # =============================================================================
365
+ # false (default): Stage 1 dimension ABAC scope services do not enforce
366
+ # external-system/source assignment scope, client-principal system binding or
367
+ # subscription owner scope (RBAC permissions still apply).
368
+ # true: enforce the Dimension ABAC certification rules (2026-09-21).
369
+ DIMENSION_ABAC_ENFORCEMENT_ENABLED=false
@@ -4,7 +4,7 @@ app:
4
4
  displayName: 'Miso Controller'
5
5
  description: 'Miso is the AI Fabrix in-tenant controller and portal layer for securely operating enterprise AI apps inside a customer’s Azure tenant. It provides Entra ID SSO, RBAC, audit logs, environment/app configuration via schemas, and safe secret handling via Key Vault references—ensuring governance, traceability, and predictable UX across portal, SDK, and CLI.'
6
6
  type: webapp
7
- version: '2.0.82'
7
+ version: '2.0.83'
8
8
  # Image Configuration
9
9
  # Set tag to match your build (e.g. aifabrix build miso-controller -t 1.0.0 then tag: 1.0.0)
10
10
  # Registry is required so the controller can pull the image (avoids "docker: not found" on the controller host).
@@ -75,6 +75,29 @@ repository:
75
75
  # - DATABASE_URL, REDIS_URL, KEYCLOAK_* → auto-generated during Azure install
76
76
  # - Other MISO_*, AZURE_*, kv:// → credentials and system parameters
77
77
  # - PORT, NODE_ENV, MISO_ENVIRONMENT → set by deployment target
78
+ # - LOCATION → resolved from the platform match below
79
+
80
+ # =============================================================================
81
+ # Platform Resolution (target Azure resource group decides)
82
+ # =============================================================================
83
+ # One controller per installation (MISO_ENVIRONMENT=miso), so the values that vary
84
+ # are stack-level, not per environment: there is no `environments:` section.
85
+ # env.template consumes these names as {NAME}.
86
+ platforms:
87
+ - resource: aifabrix-int-{platform}
88
+ name: aifabrix
89
+ options: [dev, tst, pro]
90
+ configuration:
91
+ - name: LOCATION
92
+ value: 'swedencentral'
93
+
94
+ - resource: aifabrix-ce-*
95
+ name: '*'
96
+ # The group carries no dev|tst|pro token, so the platform is declared.
97
+ platform: dev
98
+ configuration:
99
+ - name: LOCATION
100
+ value: 'swedencentral'
78
101
 
79
102
  configuration:
80
103
  # -------------------------------------------------------------------------