feat(api-contract): add @chatbotx.io/api-contract package and implement public routers from it - #1069
Open
realcodesiman wants to merge 5 commits into
Open
feat(api-contract): add @chatbotx.io/api-contract package and implement public routers from it#1069realcodesiman wants to merge 5 commits into
realcodesiman wants to merge 5 commits into
Conversation
…s to api/private.ts Pure mechanical rename across ~61 feature directories, extracted fresh off main instead of cherry-picked from the migration branch since many of those paths also carry unrelated logic changes there. Excludes ads-campaign, which no longer exists on the source branch.
Adds a tokenHash column and moves workspace bearer-token lookup to hash-first with a plaintext fallback for the deploy-to-migration gap. The fallback and the token column removal are deliberately deferred to a follow-up once the legacy-plaintext warning log has been silent for a release. Also generalizes channel-api-rate-limit.ts into api-rate-limit.ts (adds a scope param) and pulls authorize-workspace-access.ts forward as shared owner-quota/trial-gate infrastructure, since the token-auth middleware needs both.
…ernal router Consolidates the three oRPC auth-stack exports onto one instanceof-based error mapper (was three duplicated error.name checks), adding an ActionValidationError -> 422 mapping. Wires the owner-quota/trial gate from authorize-workspace-access.ts into workspaceAuthorizedMidddleware so an oRPC mutation can't bypass the gate a server action already enforces for the same operation (invariant #14: read/delete stays open on an expired workspace). Splits the OpenAPI REST surface so /api/[[...rest]] only ever serves publicRouter (workspace-token / channel-token authed procedures) instead of the full session-authed router. A procedure missing from publicRouter now 404s instead of silently answering to a session cookie. A dev-only /api-internal mirrors the old full-router behavior for local Scalar debugging and 404s in production; the builder UI is unaffected since it calls the untouched /rpc route, not /api.
8 tasks
…nt public routers from it
Introduces a stable, versioned contract package (implement(contract) pattern)
for the public v1 workspace-token API surface, replacing per-feature ad-hoc
.route({...}) builder calls. A contract carries every field the OpenAPI
generator needs (route, input, output, errors) independent of the handler
implementation, so MCP tool names (derived from operationId) and hard-coded
Postman/CLI paths stop drifting silently with unrelated refactors.
Rewires 18 of the public router's workspace-token API modules onto the new
contracts. Left three untouched: tags/api/token-auth.ts still calls
tagService methods (create/update/deleteMany) that don't exist until a later
repository-migration PR, and contacts/webhooks aren't part of this contract
migration at all yet (no contract module exists for them).
Fixes a DB-import leak found during review: two contract resource files
imported schema-only symbols from the bare @chatbotx.io/business package
root, which transitively pulls in service modules that instantiate a
Postgres Pool at module scope -- undermining the package's whole point of
being testable without a live database. Added dedicated schema-only subpath
exports (inbox/schema, integration-whatsapp/schema) instead.
Fixes a second regression found during review: custom-field and bot-field
create/update inputs used a bare z.string() for the name field instead of
the shared zodFieldName() validator, silently dropping the guard against
naming a field with the reserved "bot_field:" prefix (which would collide
with the reference-token format used by the remap engine). Both now import
zodFieldName() from @chatbotx.io/flow-config, matching the pre-existing
builder-side schemas exactly.
Also fixes a stale packages/public-apis mention in AGENTS.md's package table
and deletes the now-obsolete public-api-tooling skill doc.
realcodesiman
force-pushed
the
feat/api-contract-package
branch
from
August 30, 2026 23:12
2f6c823 to
688b31a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
packages/api-contract(46 files), a stable, versioned contract package (implement(contract)pattern) for the public v1 workspace-token API surface, replacing per-feature ad-hoc.route({...})builder calls. A contract carries every field the OpenAPI generator needs (route, input, output, errors) independent of the handler implementation, so MCP tool names (derived fromoperationId) and hard-coded Postman/CLI paths stop drifting silently with unrelated refactors.tags/api/token-auth.tsstill callstagServicemethods (create/update/deleteMany) that don't exist until PR-5's repository migration;contactsandwebhooks(generic, notexternal-webhooks) aren't part of this contract migration at all yet — no contract module exists for either.Stacked on #1065 (PR-1), #1066 (PR-2), and #1068 (PR-3) — merge those first for this diff to shrink to its own ~3k lines.
Bugs found and fixed during review (before this PR was opened)
inbox/resource.tsandwhatsapp-message-template/resource.tsimported schema-only symbols from the bare@chatbotx.io/businesspackage root, which transitively pulls in service modules that instantiate a PostgresPoolat module scope — undermining the whole point of a pure, testable-without-a-database contract package. Added dedicated schema-only subpath exports (business/inbox/schema,business/integration-whatsapp/schema) instead. Verified by tracing the full transitive import chain and by importing the package's entrypoint under a strippedenv -ienvironment with zero errors.custom-fieldandbot-fieldcreate/update inputs used a barez.string()for thenamefield instead of the sharedzodFieldName()validator, dropping the guard against naming a field with the reservedbot_field:prefix (which would collide with the reference-token format the remap engine relies on). This bug pre-existed on the source migration branch too — not something introduced by extraction. Both now importzodFieldName()from@chatbotx.io/flow-config, matching the existing builder-side schemas exactly. Verified empirically: the schema now rejects abot_field:-prefixed name and accepts a normal one.Notes for reviewers
apps/builder/__tests__/public-spec-snapshot.test.tscovers only the tags contract (/v1/tags) — its own docstring is scoped correctly, but be aware it is not yet a full-surface OpenAPI drift guard for the other ~19 contract modules this PR adds/rewires. Worth a follow-up to extend it to the merged public spec.packages/public-apismention inAGENTS.md's package table and deletes the now-obsoletepublic-api-toolingskill doc.Test plan