aws / aws/graph-explorer

Validate connector fetch boundaries with Zod and brand label types

Open
#2,078 0 comments 0 reactions 0 assignees View on GitHub
connection internal schema tech debt
Dominant language
TypeScript
Stars
481
Forks
108
Avg merge
6d 8h
Merged PRs (30d)
5

Description

## Description

Surfaced during the code review of the openCypher schema-sync batching change (see #2076). The connector fetch boundaries encode uncertainty in ways AGENTS.md discourages, and the fixes are cross query-language (Gremlin, openCypher, SPARQL), so they were deliberately kept out of that focused change. Capturing them here as tech debt.

## Improvements

### 1. Validate fetch responses at the boundary with Zod

`OpenCypherFetch` (and the Gremlin/SPARQL equivalents) return an unchecked cast — the caller asserts a `Raw*Response` shape that is never validated. The schema-sync response types then encode absence as `results?: …` plus a `?? []` fallback at each use. AGENTS.md: "Prefer Zod at boundaries to enforce contract and strong typing" and "Do not encode uncertainty as adapters, defaults, optionals, spreads, or catch blocks. Resolve it into the owned contract."

Resolve by schematizing the entity shapes (`OCVertex`/`OCEdge`, and Gremlin/SPARQL analogues) and parsing responses at the boundary: `results` defaults to `[]` (removing the optional and the `?? []`), and each row is shape-validated via `safeParse` (preserving skip-malformed behavior while replacing hand-rolled truthiness guards).

### 2. Dishonest element types vs. runtime guards

Response element types declare fully-formed entities (e.g. `object: OCVertex`) while the consuming loops still guard `if (!ocVertex || !ocVertex["~labels"])`. Either the type over-promises or the guard is dead. Boundary validation (item 1) makes this honest — a parsed row really is the entity, and malformed rows are filtered by the schema, not by ad-hoc key checks.

### 3. Primitive Obsession — labels as raw `string[]`

Vertex/edge labels flow as bare `string`/`string[]` and are used as lookup keys into `countsByLabel` and interpolated into query fragments. AGENTS.md: "Prefer a branded type over a raw `string`/`number` whenever the value is used for a lookup or passed to a function expecting a value that represents a specific concept — an ID, a node/edge label, a type name, etc." Introduce a branded label type constructed via its creator function and thread it through the schema-sync label maps and templates across connectors.

## Scope

Cross query-language and connector-wide (Gremlin, openCypher, SPARQL). The openCypher schema-sync path (#2076) is the natural first slice; the branded-label change in particular touches both the openCypher and Gremlin template/label code and should land consistently.

## Related Issues

- Surfaced from #2076
- Related to #2077

> [!IMPORTANT]
> Internal only — this issue is maintained by the core team and is not accepting external contributions.

Contributor guide

Open the contributing guide

Research direction

Start with AGENTS.md and the openCypher schema-sync path from #2076, then trace the Gremlin and SPARQL connector fetch boundaries and their label maps and templates. Done means boundary responses are Zod-validated, malformed rows are skipped, optional results fall back at the boundary, and branded labels are used consistently across the connector paths.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
databases
Issue type
Refactor
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
15/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.