Skip to content

feat(AF-612): import a Postman collection as a connector schema#620

Merged
babltiga merged 1 commit into
mainfrom
feature/AF-612-postman-collection-schema-source
Jul 20, 2026
Merged

feat(AF-612): import a Postman collection as a connector schema#620
babltiga merged 1 commit into
mainfrom
feature/AF-612-postman-collection-schema-source

Conversation

@babltiga

Copy link
Copy Markdown
Contributor

Closes #612

Makes a Postman Collection v2.x export a first-class apigov schema source. PostmanCollectionParser slots in behind the existing ApiSchemaParser SPI, so SchemaParserRegistry picks it up from supportedType() and POST /api-connectors/{id}/schemas needed no new route.

Mapping

Folders flatten into a slugified, deterministic operationId (billing/invoices/create-invoice, collisions suffixed -2/-3). Collection variable[] values are substituted; every remaining {{var}} — and Postman's :id param form — becomes a {var} path template, leaving base_url to the admin. Read/write classification is the usual safe-method rule, so the existing require_review_reads/require_review_writes gates apply unchanged.

Postman stores examples, not schemas, so requestSchema/responseSchema are inferred from the saved example bodies by a new JsonShapeInferrer. That fidelity gap is real and is stated in the upload UI.

Security shaped the design

api_schemas.raw_content persists the uploaded document verbatim, and Postman exports routinely carry live tokens plus arbitrary pre-request/test JavaScript. So "no secret is persisted" and "event blocks are dropped" could not hold by parsing alone.

The ApiSchemaParser SPI therefore now returns apigov.api.ParsedApiSchema (operations + detectedAuthMethod + sanitizedContent) instead of a bare list. The Postman parser returns a redacted copy of the collection — every event block and every auth credential array removed, at collection and per-request level — and DefaultApiSchemaService stores that instead of the upload. Only the declared auth type is read, surfaced as api_schemas.detected_auth_method so the admin knows what to re-enter on the connector. The other four parsers return null for both new fields and are otherwise untouched.

A v1 export is rejected 422 pointing at Postman's v2.1 export; so are documents over 5 MiB or 2000 requests (parser constants mirroring MAX_FETCH_BYTES — no new env var).

Frontend

Postman option on the schema-type select; a caveat banner carrying both required notices (inferred schemas, credentials ignored); the file picker converted from a plain button Upload to an Upload.Dragger following the CustomDriverUploadModal pattern, adding the size guard and inline error surface it previously lacked; a detected-auth column on the schema table. Also fixes canUpload, which accepted a whitespace-only file.

Two deliberate deviations from the issue

  1. No new messages.properties key. ApiGovExceptionHandler resolves one localized detail (error.api_schema_parse) and attaches the parser's English message as a non-localized reason property — the same shape all four existing parsers use. Adding per-rejection keys would have been inconsistent with that. MessagesParityTest is untouched; the seven frontend locales are updated.
  2. requestSchema/responseSchema have no consumer yet. The feat(AF-499): Data Lifecycle Manager — retention policies, right-to-erasure, proxy-enforced pseudonymization & compliance #518 SCHEMA_FIELD masking matcher takes an admin-typed dot-path, not a parsed schema. The inferred shapes are persisted in parsed_operations for a future consumer, per an explicit scoping decision.

Migrations

  • V122ALTER TYPE api_schema_type ADD VALUE 'POSTMAN_COLLECTION', with the paired .sql.conf (executeInTransaction=false) required by the V81 precedent.
  • V123 — nullable api_schemas.detected_auth_method api_auth_method.

Docs & website

docs/03-data-model.md, docs/04-api-spec.md (new Postman collection import section), docs/05-backend.md, docs/17-api-governance.md, website/index.html, website/docs/index.html. No new env var, so docs/09-deployment.md and the CLAUDE.md env table are deliberately unchanged.

Verification

Check Result
New parser + inferrer tests 28 + 10, green
Full backend unit suite 4610 pass, 0 failures
ApplicationModulesTest, ApiPackageDependencyTest, MessagesParityTest green
Frontend lint / typecheck / test:coverage / build green — 1283 tests, 93.78% lines / 83.82% branches
Website HTML tag-balance parsed + copy verified rendered in a browser

Not run locally: Testcontainers integration tests and the Playwright e2e suite — Docker is unavailable in my environment. All 699 backend errors in the full run traced to Could not find a valid Docker environment; every one aborts at container startup before reaching application code. That means the two migrations are unverified against a real PostgreSQL — they follow the V81/V100 patterns exactly and the entity mapping matches ApiConnectorEntity.authMethod, but CI is the first real check. The new e2e spec (admin imports a Postman collection as a connector schema) also has not been executed; it asserts the flattened ids, the {id} template, the detected-auth tag, and that neither the export's token nor its script text survives into the operation catalog. Please watch the backend and e2e CI jobs.

Noted, not fixed

DefaultApiSchemaService.fetch guards sourceUrl with a scheme check only — no loopback/link-local/RFC1918 block, so http://169.254.169.254/… is reachable by any connector-manage holder. Postman reuses that guard unchanged, as the issue asked. Hardening it affects all five schema types equally and belongs in its own issue.

Teams without an OpenAPI/WSDL/SDL/proto document usually do have a Postman
collection that is already the de-facto contract. PostmanCollectionParser
accepts a Collection v2.x export behind the existing ApiSchemaParser SPI, so
neither SchemaParserRegistry nor POST /api-connectors/{id}/schemas changed.

Folders flatten into a slugified, deterministic operationId; collection
variable[] values are substituted and every remaining {{var}} (and Postman's
:id form) becomes a {var} path template. Postman stores examples rather than
schemas, so requestSchema/responseSchema are inferred by JsonShapeInferrer --
a real fidelity gap, stated in the upload UI.

Two security properties drove the design. Only the declared auth *type* is
read (surfaced as api_schemas.detected_auth_method so the admin knows what to
re-enter), never a credential value; and event blocks -- arbitrary
pre-request/test JavaScript -- are dropped entirely. Since raw_content
persists the document verbatim, neither could hold by parsing alone, so the
SPI now returns ParsedApiSchema (operations + detectedAuthMethod +
sanitizedContent) and the parser hands back a redacted copy that is stored in
place of the upload. The other four parsers return null for both new fields.

A v1 export is rejected 422 pointing at Postman's v2.1 export, as are
documents over 5 MiB or 2000 requests.

Frontend: Postman option on the schema-type select, a caveat banner covering
both notices, the file picker converted to an Upload.Dragger with the size
guard and error surface it previously lacked, and a detected-auth column.

Docs: 03-data-model, 04-api-spec, 05-backend, 17-api-governance,
website/index.html, website/docs/index.html.

Closes #612
@github-actions

Copy link
Copy Markdown
Contributor

Frontend Test Results

1 283 tests  +6   1 283 ✅ +6   4m 36s ⏱️ +12s
  168 suites ±0       0 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit b410257. ± Comparison against base commit edc5666.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Report for Frontend Coverage (frontend)

Status Category Percentage Covered / Total
🟢 Lines 93.78% (🎯 90%) 2069 / 2206
🟢 Statements 91.76% (🎯 90%) 2307 / 2514
🟢 Functions 90.96% (🎯 90%) 634 / 697
🟢 Branches 83.82% (🎯 80%) 1296 / 1546
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
frontend/src/utils/enumLabels.ts 96.52% 100% 90.56% 96.5% 192, 200, 319, 444, 502
Generated in workflow #800 for commit b410257 by the Vitest Coverage Report Action

@github-actions

Copy link
Copy Markdown
Contributor

Backend Test Results

5 373 tests  +41   5 373 ✅ +41   15m 27s ⏱️ - 1m 32s
  671 suites + 2       0 💤 ± 0 
  671 files   + 2       0 ❌ ± 0 

Results for commit b410257. ± Comparison against base commit edc5666.

@github-actions

Copy link
Copy Markdown
Contributor

Backend Code Coverage

Overall Project 93.26% -0.01% 🍏
Files changed 98.21% 🍏

File Coverage
JsonShapeInferrer.java 100% 🍏
SchemaParserRegistry.java 100% 🍏
GraphQlSchemaParser.java 100% 🍏
ApiSchemaResponse.java 100% 🍏
ApiSchemaView.java 100% 🍏
ParsedApiSchema.java 100% 🍏
ApiSchemaType.java 100% 🍏
PostmanCollectionParser.java 97.51% -2.49% 🍏
WsdlSchemaParser.java 96.86% 🍏
ProtoSchemaParser.java 94.26% 🍏
OpenApiSchemaParser.java 89.58% 🍏
DefaultApiSchemaService.java 86.95% 🍏

@babltiga
babltiga merged commit 8e1f543 into main Jul 20, 2026
27 checks passed
@babltiga
babltiga deleted the feature/AF-612-postman-collection-schema-source branch July 20, 2026 13:57
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.

apigov: import a Postman collection export as an API connector schema source

1 participant