Skip to content

feat(integrations): notion in-box shim + image provisioning + enable flag (T2)#74

Merged
madarco merged 1 commit into
add-ticketing-integrationsfrom
agentbox/notion-t2
Jun 6, 2026
Merged

feat(integrations): notion in-box shim + image provisioning + enable flag (T2)#74
madarco merged 1 commit into
add-ticketing-integrationsfrom
agentbox/notion-t2

Conversation

@madarco
Copy link
Copy Markdown
Owner

@madarco madarco commented Jun 6, 2026

Summary

Ships T2 of the Notion integration: an in-box ntn / notion shim
modeled on gh-shim, image provisioning across all providers
(docker / hetzner / vercel / e2b — daytona stays shim-less to match its
T1 gh/git decision), and a typed config flag integrations.notion.enabled
(default off) gated at the relay. The host's authenticated ntn
runs the call; the box never holds a Notion token.

Builds on T1 (PR #73). T3 (doctor + docs site) and T4 (nested-box e2e)
remain.

Decisions called out

  • comment.add dropped from T1's connector. ntn has no top-level
    comment subcommand — the only host path is ntn api v1/comments -X POST -f … which the T1 api op refuses (GET-only). There were
    no callers (T1 just merged, no shim yet), so a forward-only drop is
    cleaner than carrying dead surface. The shim refuses notion comment add … with a "deferred from T2" message. A focused follow-up will
    need a Notion-API-aware payload translator that maps CLI flags to the
    structured POST body.
  • whoami read op added so ntn whoami doesn't widen the api
    allowlist (it reuses the same auth check the connector already
    declared as the T3 doctor probe).
  • Gate placement: relay (refuseIfIntegrationDisabled in
    packages/relay/src/integrations.ts), wired into BOTH
    handleIntegrationRpc (docker) AND runIntegrationRpc (cloud) per
    the "fix across all providers" rule. Re-reads the layered config per
    call so flipping the flag takes effect without bouncing the relay
    (mirrors loadAutopauseConfig). Disabled → exit 65 with a
    agentbox config set --project integrations.notion.enabled true hint;
    no host process is touched.
  • notion is a symlink to ntn, not a separate shim. Both
    invocations behave identically; the notion name is the per-service
    surface from docs/integrations_backlog.md.
  • Config parser, merger, writer were taught N-level nested keys so
    integrations.notion.enabled is natural YAML
    (integrations: { notion: { enabled: true } }) — the previous code
    only handled 1-level branch.leaf.

Test plan

  • pnpm -w typecheck green
  • pnpm -w test green (487 tests + 1 skipped, including the new
    shim allowlist, config 3-level cascade + roundtrip, relay docker gate,
    cloud gate)
  • pnpm -w build green; ntn-shim staged into all four provider
    runtime trees (docker / hetzner / vercel / e2b)
  • Manual shim smoke: whoami / api / pages create / pages update route to ctl; pages list / comment add / login /
    datasources etc. refuse with exit 2 and a clear stderr
  • Live in-box smoke deferred to T4 (nested-box e2e is its own task)
  • T3 will follow with agentbox doctor reporting + the public docs
    site

Note

Medium Risk
Touches relay integration dispatch and layered config parsing for all providers; mis-wiring could block or accidentally allow Notion RPCs, but defaults stay off and the gate fails closed.

Overview
Adds T2 of the Notion integration: in-box ntn / notion commands (strict allowlist shim → agentbox-ctl integration notion …) with the shim baked into docker, Hetzner, Vercel, and E2B images (staging, Dockerfile.box, provider install scripts, and runtime-assets).

Introduces integrations.notion.enabled (default false) in typed config, with parser/merge/write updated for nested dotted keys so YAML can use integrations.notion.enabled. The relay enforces enablement via refuseIfIntegrationDisabled on both docker POST /rpc and cloud runIntegrationRpc — exit 65 and a config hint when off, before readiness checks, prompts, or host ntn spawn.

Connector cleanup: drops unused comment.add, adds read whoami; shim rejects deferred comment flows. Tests cover shim routing, config cascade/roundtrip, and relay gate behavior.

Reviewed by Cursor Bugbot for commit 60a484a. Configure here.

…flag (T2)

Lets agents in a sandbox type `notion …` / `ntn …` and have the call
routed through the host relay to the host's authenticated `ntn` CLI;
gated by a new typed config flag so the integration is opt-in.

Surface
- packages/sandbox-docker/scripts/ntn-shim — bash shim modeled on
  gh-shim. Strict allowlist: `whoami`, `api <endpoint>`, `pages create`,
  `pages update`. Anything else dies with a clear message. Installed at
  /usr/local/bin/ntn; /usr/local/bin/notion is a symlink to the same
  shim (per docs/integrations_backlog.md's per-service surface naming).

Image provisioning (all providers except daytona, which stays
shim-less to match its T1 gh/git decision)
- Dockerfile.box: COPY ntn-shim, chmod, symlink notion.
- apps/cli/scripts/stage-runtime.mjs: stage ntn-shim into the docker
  contextFiles + execBitFiles plus the hetzner / vercel / e2b file lists.
- Hetzner install-box.sh, Vercel provision.sh, E2B build-template.sh:
  install + symlink the shim.
- Each provider's runtime-assets.ts: map the shim name + remote /tmp
  path so the staged file gets uploaded into the prepare VM.

Config flag (opt-in by default)
- packages/config/src/types.ts: new `integrations.notion.enabled` key
  (UserConfig, EffectiveConfig, BUILT_IN_DEFAULTS, KEY_REGISTRY entry).
- parse.ts / load.ts / write.ts: parser, merger, and writer now walk
  N-level dotted leaves so the 3-level path is natural YAML
  (`integrations: { notion: { enabled: true } }`).

Relay gate (cross-provider)
- packages/relay/src/integrations.ts: `refuseIfIntegrationDisabled`
  re-reads the layered config per call (matches loadAutopauseConfig).
  Disabled → exit 65 with a config-set hint; no host process touched.
- Wired into both `handleIntegrationRpc` (server.ts, docker) and
  `runIntegrationRpc` (host-actions.ts, daytona/hetzner/vercel/e2b) per
  the "fix across all providers" rule. Order: refuseIntegrationCall
  first (op-level), then enablement gate, then readiness probe, then
  prompt. Same order on both providers — a malformed-args-to-disabled-
  integration call returns the same envelope shape.

Connector cleanup (T1 minimal change)
- packages/integrations/src/connectors/notion.ts: drop `comment.add`.
  `ntn` exposes no top-level `comment` subcommand; the only host path
  is `ntn api v1/comments -X POST -f …` which the T1 `api` op refuses
  (GET-only). No callers exist (T1 just merged), so a forward-only
  drop is cleaner than carrying dead surface. The shim refuses
  `notion comment add …` with a "deferred from T2" message. Comments
  tracked as a focused follow-up (need a Notion-API-aware payload
  translator that maps CLI flags to the structured POST body).
- Added `whoami` read op so `ntn whoami` doesn't widen the `api`
  allowlist. The connector already declared `api v1/users/me` as the
  T3 doctor probe — `whoami` reuses the same auth check via its
  dedicated host CLI subcommand.

Tests (vitest, no docker, no network)
- packages/ctl/test/gh-and-shims.test.ts: extended with NTN_SHIM cases
  mirroring the gh / git shim patterns.
- packages/config/test/merge-precedence.test.ts +
  set-unset-roundtrip.test.ts: cover the new 3-level cascade and the
  YAML pruning roundtrip.
- packages/relay/test/integrations.test.ts: workspace agentbox.yaml in
  beforeEach now flips the integration on; new tests for the disabled
  envelope and the injectable-loader unit shape.
- packages/relay/test/host-actions.test.ts: parity check for the cloud
  gate.

Docs
- docs/notion_backlog.md: T2 flipped to done with the comment-handling +
  gate-placement decisions and the comments-deferred note.

T3 (doctor + docs site) and T4 (nested-box e2e) remain.
@vercel
Copy link
Copy Markdown

vercel Bot commented Jun 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agentbox-web Ready Ready Preview, Comment Jun 6, 2026 2:39pm

Request Review

@madarco madarco merged commit 9a89bf8 into add-ticketing-integrations Jun 6, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant