Commit Graph
342 Commits
Author SHA1 Message Date
kevinveenbirkenbach d0698daa5e Merge pull request #414 from pragepani/feature/web-app-wazuh/add-role
feat(web-app-wazuh): add Wazuh SIEM role with OIDC/LDAP RBAC
2026-10-19 14:35:24 +02:00
evangelostsak 1b19fe7df3 docs(requirements): 039 test full meshes on the WireGuard role's own CI row
Compose app rows no longer spend deploy time on WireGuard. The full-mesh
test runs on svc-net-wireguard's own row, the role deploys where its group
puts it, and production keeps WireGuard for every role.
2026-10-16 21:26:16 +02:00
evangelostsak 6cfe1f1f52 docs(requirements): list 038 under the archive 2026-10-16 08:46:23 +02:00
evangelostsak 0c42f53ca8 docs(requirements): archive 038, every criterion closed
The last two criteria closed on fork run 38836531620, a manual steer of
svc-db-redis#0 in compose with the vpn axis enforced. Its job log shows
INFINITO_COMPOSE_VPN=true reaching the step, svc-net-wireguard deployed beside
the app and skipped on the CI host, which holds no mesh, and the CLI test of
svc-net-wireguard writing two full meshes of two members each. The inner play
passed four handshake gates and four MTU probes, and the test printed all six
reachability assertions: I and II reach each other, II and III reach each
other, I and III do not.

With nothing left open, make requirements-archive moved its heading into the
README and deleted the file.
2026-10-16 08:46:23 +02:00
evangelostsak 20c42ab48b docs(requirements): 038 full-mesh WireGuard for Compose deployments
Compose hosts of one inventory join full meshes that each role opts into
through its networks.meshes, with no swarm manager and nothing hardcoded into
a role. The vpn axis decides per CI row, on a role's smallest variant only,
and a CLI test proves the shape on three throwaway hosts: I and II reach each
other, II and III reach each other, I and III do not.
2026-10-16 03:40:15 +02:00
evangelostsak 91de85a4d5 docs(requirements): list 037 under the archive 2026-10-16 01:43:33 +02:00
evangelostsak 86745f92ec docs(requirements): archive 037, every criterion closed
Ticked with evidence from the local lab and the fork's CI runs: both VPNs
including the backup host, swarm advertising on the mesh, the prologue and
both passes over the mesh, key rotation converging, the mesh-off arm, the
axis rotation, pin and title, the measured MTU, nothing naming a mesh, the
three-mesh example, the role installing its own tooling, the NFS mount over
the mesh, the controller reaching the hosts it deploys over, the gate, and
swarm control, overlay and NFS carried over the mesh.

Dropped: rotating over a live mesh connection, which the prologue avoids by
rotating before the transport moves; the role being inert in compose, which
the backup host now contradicts; the failing-mount half of the NFS
criterion; and the port-reachability criterion with its claim in the user
story.

With nothing left open, make requirements-archive moved its heading into the
README and deleted the file.
2026-10-16 01:43:33 +02:00
evangelostsak 6f4783d3ac docs(requirements): meshes as the roles' own network declarations
Checked: every role ships its mesh fields empty, one module reads them, and
the three-mesh layout deployed svc-dns-unbound end to end on the local lab
with the same members and addresses as before the move.
2026-10-14 15:03:41 +02:00
evangelostsak eb90249d93 docs(requirements): add the multi-mesh and example criteria to 037
The multi-mesh spoke criterion is checked: the three-mesh example deployed
svc-dns-unbound end to end on the local lab with the NFS server up on beta and
gamma. The other two stay open until the CI dispatch has run.
2026-10-14 11:23:23 +02:00
evangelostsak 5a83785b53 Merge remote-tracking branch 'origin/main' into feature/svc-net-wireguard 2026-10-09 12:00:07 +02:00
Prageeth Panicker f5b552a667 Merge remote-tracking branch 'origin/main' into feature/web-app-wazuh/add-role 2026-10-09 08:34:37 +00:00
kevinveenbirkenbachandClaude Opus 5.5 c76eef2cae docs(requirements): add 037, World Monitor behind the oauth2-proxy gate
Requirement for a web-app-worldmonitor role: the upstream four-service
stack (dashboard, AIS relay, Redis, REST proxy) behind the platform's
Keycloak login through oauth2-proxy, in compose and in swarm.

It records what the upstream self-hosted mode offers and lacks, eleven
proposed decisions the operator has to confirm before implementation,
the target role layout and the acceptance criteria.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-08 00:39:49 +02:00
Prageeth Panicker 885de8e4a6 fix(web-app-wazuh): resolve platform-drift lint/integration failures from the 900-commit main sync
Seven real, branch-caused failures surfaced after rebasing onto main
(v14.0.0, ~900 commits):

- opensearch_dashboards_yml volume: type: config -> type: secret
  (renders a live OIDC client secret; was world-readable at 0444 in a
  volume type the platform treats as non-sensitive, same fix pattern
  as web-app-gitlab's rails_secrets_yml)
- meta/networks.yml: local.subnet collided with web-app-litellm
- meta/services.yml: indexer/console ports collided with
  svc-ai-litellm and web-app-openclaw (both added during the gap)
- compose.yml.j2: healthcheck interval/timeout/start_period now go
  through the SPOT lookup instead of hardcoded values
- README.md: regenerated Quick Setup section, fixed credits link
  formatting
- docs/requirements/035-mcp-proxy-expansion.md: added web-app-wazuh
  to the adapter_candidate list (has a real, currently-unpublished
  API surface - manager :55000, indexer :9200 - not yet evaluated
  for an MCP adapter, same bucket web-app-checkmk/prometheus sat in
  before promotion)

Two regressions caught by re-verification and fixed in the same pass:
meta/services.yml briefly reached into a role var directly (fixed to
use the lookup('config', ...) pattern already used elsewhere), and the
credits-link fix dropped required bold markdown.

Remaining test failures after this fix are confirmed pre-existing and
unrelated: svc-net-tor's nftables guard rule (kernel EOPNOTSUPP), an
INFINITO_SWARM_STEP_TIMEOUT_MINUTES Makefile/default.env drift, and a
CI chunk-budget drift.
2026-10-06 05:15:14 +00:00
evangelostsak 874aea328c docs(037): record the prologue and the two passes over the tunnel
Renames the mesh-only first pass to the prologue it always was, since
PASS 1 and PASS 2 now both name application deploys, and states why the
credential reset cannot move to the direct arm's slot.
2026-10-06 02:35:55 +02:00
evangelostsak 996febdc89 revert(swarm-test): drill the meshed arm in full again
Narrowing the meshed drill to its backup half bought budget by giving
up the recovery legs over the mesh. The budget overrun is worth measuring
before it is designed around, so the pre-drill pass and the full teardown and
recover come back. Reverts a27b093c4.
2026-10-05 18:06:41 +02:00
evangelostsak d4b2f72946 docs(037): record the meshed arm's backup-half drill
The drill is no longer an exception to deploying once, and the probe's
tie-break now costs the backup host's deploy rather than a full one.
2026-10-05 13:27:29 +02:00
evangelostsak 4e44d7fb84 Merge remote-tracking branch 'upstream/main' into feature/svc-net-wireguard
No conflicts. Two files were touched by both sides and both kept each
side: the Makefile, where upstream retires the mcp-audit target and this
branch pins the throwaway cluster's vpn axis, and requirement 035, where
the role table keeps the single svc-net-wireguard row.

Incoming carries the fixes for two applications this branch's last run
failed on -- penpot probing its frontend without curl, and mobilizon's
postgres 18 migrations -- plus dependency bumps and a lint repair.

Gates on the merged tree: unit 6202, lint 523, integration 330,
ansible-lint clean.
2026-10-05 12:17:12 +02:00
evangelostsak b5b0a94c3a docs(037): say which suite the pre-drill pass holds back
The browser suite, not both: the CLI suite declares required_by and the
deploy refuses to finish without it.
2026-10-04 21:11:00 +02:00
kevinveenbirkenbachandClaude Opus 5.5 5b002678df docs(mcp): remove the generated audit report
The report aggregated each role's meta/mcp.yml into one table, and its
freshness test failed on every image-version bump of an MCP-serving role,
because the updater edits services.yml and nothing regenerates the committed
report. The table added nothing the sources lack: scope and credential subject
were identical for every role, so it restated its inputs.

The generator, the report, its freshness test, make mcp-audit and the i8mcau
alias go, and make docs no longer calls the generator. The metadata stays in
each role's meta/mcp.yml, where test_mcp_schema.py enforces its shape, and
requirement 035 now says so. The classification and completeness lints stay,
because they check the lists in 035 against the roles, not the report.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-04 14:36:52 +02:00
evangelostsak 2a866719f9 docs(037): record the drill's exception to deploying once
Why a meshed round deploys twice when a drill is coming and once when it
is not, why the end-to-end suites belong to the pass after the drill, and
why the condition is asked of the drill rather than decided again.
2026-10-04 12:25:54 +02:00
evangelostsak e456b1eee6 Merge remote-tracking branch 'origin/main' into feature/svc-net-wireguard
One conflict, in the MCP exclusion list of requirement 035. Both sides
edited the same line: main added svc-net-tor-smtp, this branch replaced the
three svc-net-wireguard-{core,plain,firewalled} entries with the single
svc-net-wireguard it deploys. Resolved to the union of both — 24 entries —
which is what the merged tree actually holds.

Everything else merged clean and was checked for overlap rather than
assumed: no reference anywhere still names the three replaced roles;
matrix.py kept main's PRIMARY_APPS alongside the reordered round, and the
bootstrap pass does not need it, since only one template reads it and
group_vars defaults it empty; and main's ansible.cfg addition sits in
[defaults], so the ssh_args the mesh tool derives its own connection
settings from are untouched.
2026-10-03 02:29:45 +02:00
evangelostsak 28ed194f8a docs(037): record the single deploy over the mesh
Why the first pass stops at the mesh, and what the meshed row therefore
stops covering: the second deploy itself, so no re-run proving a redeploy
changes nothing, and no async update pass. Every direct-transport row still
deploys twice, so that coverage moves across the axis rather than
disappearing.
2026-10-03 02:09:16 +02:00
evangelostsak dc14e8a3a8 fix(mesh): keep every member on the address it already holds
The offset came from the spoke's position in a sorted list, so a host that
sorts earlier renumbered every member behind it. `wg syncconf` carries keys
and peers onto a live interface and never its address, so a renumbered member
keeps answering on the old address while the peers and the inventory have
moved to the new one -- and the address it gave up can be handed to a new
member while the old owner still holds it.

The planner now reuses the addresses already on disk and allocates only an
unseen member, from the lowest free offset. A value outside the subnet, a
duplicate, and the hub's own offset are refused, so a mirrored host_vars
cannot hand a spoke the hub's address. Rotation keeps addresses: it replaces
identities, not addresses.

The routing assertions re-planned the mesh and compared the result with
itself, so a writer that stored the mesh subnet in place of the routed range
would have passed; they now read the entry off disk, which is what the role
reads.
2026-10-02 00:54:20 +02:00
evangelostsak 3cd6860a18 docs(037): the seam rotates the mesh on purpose
Records that the round asks for the rotation rather than inheriting it, so
the two rotation criteria are exercised every round.
2026-09-29 00:51:21 +02:00
evangelostsak 8c4b294252 docs(037): record that peers are dialled at the underlay address
States why the address is only given where inventory names do not resolve
for every member.
2026-09-27 02:05:21 +02:00
evangelostsak 8e75ceadb7 docs(037): describe the rotation inside the seam
Records why the nodes converge before the controller joins, and reopens the
key-rotation criterion: the rotation did sever the run, so the box was ticked
on an assumption rather than on evidence.
2026-09-26 21:29:01 +02:00
evangelostsak 1e59291866 docs(requirements): rewrite the transport and gate for the mesh axis
The controller is now a mesh member rather than staying off it behind a
gateway hop, and the two-phase seam falls between the two deploy passes the
round already had, so the second runs over the tunnel at no extra CI cost.

The gate and the axis are separated: whether a swarm deploy carries the mesh
is decided per run, and when it does the mesh is mandatory. Swarm and the mesh
are independent, so an off run omits the role entirely and proves swarm still
works with no mesh logic in the path.

The MTU is measured rather than declared. Criteria follow: three new ones for
the transport, two for the axis arms, one for the tooling, and the MTU one is
unchecked again because what it claimed has changed.
2026-09-26 01:34:14 +02:00
evangelostsak 0a6700e378 Merge origin/main into feature/svc-net-wireguard
Brings in 225 commits, including the merged web-app-openbao work and the
LMStudio loopback fix.

Seven conflicts:

- The legacy svc-net-wireguard-core/plain/firewalled roles this branch deleted
  in e706170a0 were modified upstream. The deletion stands, which is the whole
  premise of the branch.
- The MCP audit takes upstream's list plus svc-net-firewall, with the three
  legacy wireguard entries collapsed into the single svc-net-wireguard: 23.
- web-app-openbao/README.md takes main's reviewed version wholesale.
- matrix.py takes both sides: upstream's app_id argument to _reset_credentials
  and this branch's _write_mesh call after it.

The merge pushed matrix.py to 511 lines against the 500 cap, so the step
runner moved to utils/tests/swarm/run.py, which is self-contained and leaves
matrix.py at 427. Its test moved with it.
2026-09-24 21:14:25 +02:00
Alejandro Roman c8894b2dd2 Merge remote-tracking branch 'upstream/main' into feature/role-stalwart-mail-swarm 2026-09-22 22:33:13 +04:00
Alejandro Roman 9df3287adf Merge remote-tracking branch 'upstream/main' into feature/role-stalwart-mail-swarm 2026-09-22 12:16:44 +04:00
evangelostsak 2527ff8fd4 Merge main into feature/web-app-openbao
Brings in the LMStudio loopback fix (LMS_SERVER_HOST=0.0.0.0 plus the
readiness probe changes), which is what failed the LiteLLM model warm and took
Matrix, Mattermost, Moodle, XWiki and Zammad down with it on the last run.

Also folds CLAUDE.md and GEMINI.md into AGENTS.md, and carries upstream's own
regeneration of the MCP audit report, which matches ours.

No conflicts.
2026-09-21 23:07:27 +02:00
kevinveenbirkenbachandClaude Opus 5 f40d627a1b docs(agents): merge the tool-specific files into AGENTS.md
CLAUDE.md and GEMINI.md existed as per-runtime extensions of AGENTS.md, and
only one of them carried anything at all: GEMINI.md stated that it had no
additions, while CLAUDE.md held rules that bind every runtime anyway — the
permission announcement, the make-over-raw preference, the loop, chain and
heredoc bans, the stream-the-log-to-/tmp rule, the CI-evidence rule, the push
ban and the comment rule. A rule that binds every agent does not belong in one
agent's file. AGENTS.md absorbs them and now states that no tool-specific
extension file exists; agents whose runtime auto-loads a different filename
reach it through their own configuration instead.

The filenames were machinery as much as prose. The PR templates, the branch
and pull-request scope tables, the settings and security docs that justified
the loop deny by "the textual CLAUDE.md rule", six requirement documents whose
push instruction linked ../../CLAUDE.md, and a test docstring citing the
shell-loop ban all named them, and now name AGENTS.md.
scripts/meta/resolve/pr/scope.sh deliberately keeps matching CLAUDE.md and
GEMINI.md: this change deletes them, and without those patterns the change
itself would not classify as agent-scope.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-21 22:51:04 +02:00
Alejandro Roman 4b9a834546 Merge remote-tracking branch 'upstream/main' into feature/role-stalwart-mail-swarm 2026-09-21 03:25:20 +04:00
evangelostsak c762924675 Merge upstream/main into feature/web-app-openbao
Brings in Kevin's AI-agent work, the svc-net-firewall role and the update
tooling. One conflict, in the MCP proxy audit: both sides appended a role to
privileged_control_plane, ours web-app-openbao and upstream svc-net-firewall.
Taken as a union at 25, which is what test_mcp_audit_completeness requires -
neither role declares meta/mcp.yml, so the audit is the only place they are
classified.
2026-09-19 20:07:00 +02:00
evangelostsak 02d024ee54 docs(requirements): check off the test-suite criterion
Lint, integration and external suites and the ruff gate all run clean with
the role and the cross-host mesh writer in place.
2026-09-19 14:54:07 +02:00
evangelostsak 416ec6954d docs(requirements): check off rotation survival and MTU proof
The swarm drill against web-app-openbao establishes both meshes, rotates
every key mid-run and completes the update pass without an operator touch,
and every spoke crosses the tunnel with a full-size payload.
2026-09-19 14:48:55 +02:00
evangelostsak ac0f08f181 docs(mcp): dispose of svc-net-wireguard as privileged control plane
The role alters host routing and forwarding, so it belongs with the roles that
require an audited operations gateway rather than general-purpose application
MCP. Absence is not a disposition, and the completeness lint enforces that.
2026-09-18 10:36:24 +02:00
evangelostsak f3f6ac0f60 docs(requirements): add 037, WireGuard transport for swarm deployments
Two hub-and-spoke meshes over the five hosts default.env already names, with
the manager as the only member of both and therefore the router between the
swarm and data planes. Records the three consequences of that shape as accepted
rather than hiding them: the hub carries worker-to-worker overlay traffic, it
carries all worker storage traffic because workers are not data-plane members,
and losing its tunnel stops running containers in a way plain swarm does not.

The subnet-collision criterion comes from the topology rather than the design:
the lab underlay is 192.168.244.0/24, Docker holds 10.208.0.0/12, and per-role
subnets sit in the lower 192.168.0.0/16, so a mesh has to be allocated clear of
all three and checked before a deploy.
2026-09-18 09:06:15 +02:00
evangelostsak d783d83560 Merge feature/web-app-openbao into feature/svc-net-wireguard
Brings this pre-swarm branch up to the current swarm-era codebase: 3681 commits
across 7221 files. Our side contributed almost nothing by comparison, so the
conflict surface stayed at the 17 files both sides had touched.

Resolutions:
- The 15 legacy svc-net-wireguard-{core,firewalled,plain} files conflicted as
  modify/delete and rename/delete (upstream renamed 01_core.yml to 00_core.yml).
  All resolved as deletions: this branch is starting wireguard over. Five more
  files of those roles came back silently because upstream had not touched them
  since the merge base, and were removed after the merge.
- sys-svc-container/templates/daemon.json.j2 took upstream's structure, which
  adds default-address-pools and json-file log limits and makes storage-driver
  conditional on DOCKER_IN_CONTAINER. Our unconditional version would have set
  fuse-overlayfs on bare-metal hosts too, so theirs is the correct semantics;
  only the value now routes through SYS_SVC_CONTAINER_STORAGE_DRIVER.
- sys-svc-container/vars/main.yml keeps that variable, which upstream never had
  and nothing supersedes, and adopts upstream's removal of the MTU comment.

Follow-up the merge itself required: the root README role table was regenerated
and the privileged_control_plane list in requirement 035 dropped from 24 to 21,
both of which still enumerated the deleted roles.
2026-09-18 00:41:03 +02:00
evangelostsak c40d7aa6da chore(wireguard): remove the role and its references to start fresh
The consolidated svc-net-wireguard role, its requirement document and the three
references that only existed to support it go away together: the lint ignore for
a load failure inside its tasks, the requirements index entry, and the tunnel
subnet variable nothing else consumed.

Left in place deliberately: the WireGuard mention in the svc-net category
description, which is upstream prose about networking roles in general rather
than anything this role owned.
2026-09-18 00:30:39 +02:00
kevinveenbirkenbachandClaude Opus 5 bf32f57b85 feat(svc-net-firewall): own the packet filter as one nftables table per role
svc-net-tor rendered its own guard script, its own unit and its own handler, and hooked the rules into DOCKER-USER with an insert, because a rule appended to a chain docker owns lands behind the RETURN docker puts there. The script flushed its chain and refilled it rule by rule, so the boundary was gone for the duration of the refill.

A role that needs packet filter rules now writes templates/nftables.conf.j2 declaring its own table and includes svc-net-firewall, which renders it to /etc/nftables.d/<role>.conf, rejects it with nft -c, loads it, reads the table back and refuses one that carries no chain. Deployed on its own the role installs nftables and the ruleset that loads every fragment at boot. That ruleset is a distribution decision, so its path follows os_family: RedHat reads /etc/sysconfig/nftables.conf, the others /etc/nftables.conf. The unit is only enabled, never started, because on Debian its ExecStop flushes the whole ruleset, docker's tables included.

One table per role removes the shared path: a fragment replaces its own table and touches no other, and docker never touches either. nft -f on an existing table merges, so each fragment creates, deletes and redeclares its table in one transaction. The tests load every fragment twice into a throwaway network namespace and require the listing to match, because a merging fragment loads twice without error and shows up only as a duplicated rule.

The tor guard now applies in both deploy modes. It was pinned to swarm while torrc binds TransPort and DNSPort on the bridge address in compose too, so on a single-host install those ports answered every on-link neighbour. The guard drops rather than admits, so nothing short-circuits another table, and ip saddr carries an implicit ipv4 dependency, which leaves the ipv6 exposure exactly where the iptables rules left it. svc-net-tor reads its own chain back and refuses a guard that drops nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-15 20:02:36 +02:00
evangelostsak 912b6cda39 Merge infinito-nexus/core#454 (feature/ai-agent-employees) into feature/web-app-openbao
Only two files were touched by both sides. env.js merged automatically: the
incoming side owns recordVideoOptions and this branch had cherry-picked that
same function from it, so the result carries one definition. README.md is the
generated roles index and both sides append rows; resolved as a union, taking
the incoming side for the three rows it edits (OnlyOffice, Open WebUI, OpenClaw)
and keeping ours only for OpenBao, then re-sorted.

The incoming side adds lint rules and resources that this role then violated.
Five fixes, each the remedy the failing rule names:

* services.openbao.ports.local.http 8081 -> 8093; svc-ai-litellm now holds 8081.
* meta/networks.yml subnet 192.168.221.0/24 -> 192.168.222.0/24; svc-ai-mcp-adapter
  now holds 221, and the suggester only sub-allocates inside occupied /24s, so
  the next free block was taken directly.
* services.email bond 1 -> 0; the entry is disabled and the resource model skips
  it before reading the weight.
* README Quick Setup regenerated from the template it had drifted from.
* Credits link the implementer, matching how they are credited elsewhere.
* docs/requirements/035-mcp-proxy-expansion.md disposes of web-app-openbao as
  privileged_control_plane, which is what a secrets manager is, and the list
  count follows.

Verified against a worktree of #454 alone so the baseline is measured rather
than assumed: lint 501 passed with only the branch-name rule failing, which
fails identically on that baseline because the worktree branch is named
merge/*; unit 5665 passed with the same three host-environment failures the
baseline has; integration 324 passed, 0 failed.
2026-09-14 16:59:39 +02:00
evangelostsak c8f0c8f246 docs(requirements): close the RBAC tier criterion and note the LAM CSP defect 2026-09-12 10:23:25 +02:00
evangelostsak d6cc7c376b docs(requirements): restate the RBAC tier criterion around the LAM group rotation 2026-09-12 00:18:10 +02:00
evangelostsak c9e6a0fddc docs(requirements): correct how the RBAC tier accounts get their password 2026-09-11 23:29:57 +02:00
evangelostsak 58aa57680e docs(requirements): correct how the RBAC tier accounts get their password 2026-09-11 21:16:14 +02:00
evangelostsak 86fcff42f1 docs(requirements): correct where the RBAC test accounts are declared 2026-09-11 20:55:08 +02:00
evangelostsak c6bf74aa0f docs(requirements): close the RBAC tier criterion and relocate the seal alert 2026-09-11 18:38:11 +02:00
kevinveenbirkenbachandClaude Opus 5 3db5820b6e fix(n8n): serve the MCP trigger over Streamable HTTP on 1.100.1 so Open WebUI can connect
Run 34421944328 n8n#1: Open WebUI 0.11.0 ships only a Streamable HTTP
MCP client. n8n 1.95.3's MCP Server Trigger speaks SSE only and answered
the client's POST to /webhook/infinito-mcp/sse with 404, so "every
registered MCP server answers Open WebUI's client" failed.

n8n moves to 1.100.1 and the managed trigger to typeVersion 2, which
serves Streamable HTTP at /mcp/<path>. meta/mcp.yml declares
transport: streamable_http at /mcp/infinito-mcp (the trigger path stays
infinito-mcp) and points source_url at the 1.100.1 tree. Open WebUI's
supported_transports drops sse, which its client never spoke; no
provider declares sse any more, so no pairing is lost.

n8n#0: the guest spec probed ${APP_BASE_URL}${MCP_ENDPOINT_PATH} and
expected a refusal of >= 300 without an event stream. The trigger is
exposure: internal, so the public vhost must answer 404; the spec now
asserts exactly that through mcpEndpointUrl(..., N8N_BASE_URL), and the
bearer guard itself is proven in-cluster by the CLI MCP contract.

Requirement 035 and the MCP audit table follow the version and
transport.

Upgrade path, read from upstream at both tags: the postgres migrations
are identical (45/45) and the only new common migration is
AddProjectDescriptionColumn, an additive nullable column; BREAKING-
CHANGES.md lists only 1.98.0 in range (route metric format, Form node
tag attributes, Node >= 20), none of which this deployment uses. A fresh
1.100.1 install ran all 89 migrations and passed the MCP bridge, server,
non-member and guest specs locally.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 12:20:46 +02:00
evangelostsak 48e230d87f docs(requirements): cross-link the OpenBao requirement to its PR
Closes the last cross-link acceptance criterion: the requirement now names
infinito-nexus/core#611 in its header and in the criterion itself, and the PR
description links back to this document. Also deep-links the upstream story
instead of pointing at the OpenProject root.
2026-09-11 00:15:35 +02:00