Skip to content

feat(repo): Added Python and TypeScript packages for RFC 9457 Problem Details#1

Merged
char0n merged 14 commits into
mainfrom
feat/model-implementation
Apr 13, 2026
Merged

feat(repo): Added Python and TypeScript packages for RFC 9457 Problem Details#1
char0n merged 14 commits into
mainfrom
feat/model-implementation

Conversation

@frankkilcommins
Copy link
Copy Markdown
Member

  • Pydantic models + FastAPI exception handlers (Python)
  • TypeScript interfaces + error utilities + type guards
  • Schema conformance tests to prevent drift from schemas
  • test coverage (30 Python tests, 47 TypeScript tests)

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces reusable RFC 9457 “Problem Details” libraries for both Python (Pydantic + FastAPI helpers) and TypeScript (types + utilities), alongside schema conformance tests and CI/release automation to keep the implementations aligned with the repo’s OpenAPI schemas.

Changes:

  • Add a new Python package (jentic-problem-details) with Pydantic models and FastAPI exception helpers, plus tests.
  • Add a new TypeScript package (@jentic/problem-details) with interfaces, type guards, error utilities, plus Vitest-based tests.
  • Add CI and release workflows to build, test, and publish the packages.

Reviewed changes

Copilot reviewed 26 out of 28 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
typescript/vitest.config.ts Adds Vitest config including coverage settings.
typescript/tsconfig.json Adds TypeScript compiler configuration for the package build.
typescript/tests/types.test.ts Adds TypeScript tests for types and type guards.
typescript/tests/schema-conformance.test.ts Adds schema conformance tests against YAML schemas.
typescript/tests/errors.test.ts Adds tests for ProblemDetailError and factory helpers.
typescript/src/types.ts Defines ProblemDetail/ErrorItem and runtime type guards.
typescript/src/index.ts Provides package public exports and documentation header.
typescript/src/errors.ts Implements ProblemDetailError and factory helpers for common HTTP errors.
typescript/README.md Adds TypeScript package documentation and usage examples.
typescript/package.json Defines TypeScript package metadata, scripts, and dev dependencies.
typescript/package-lock.json Locks dependency tree for the TypeScript package.
typescript/.gitignore Adds TypeScript-package specific ignores.
README.md Updates repository-level README with Python/TypeScript usage and structure.
python/tests/test_schema_conformance.py Adds Python schema conformance tests (Pydantic vs OpenAPI schema).
python/tests/test_responses.py Adds tests for FastAPI response helpers/exceptions.
python/tests/test_models.py Adds tests for Pydantic model behavior and validation constraints.
python/src/jentic/problem_details/responses.py Implements FastAPI HTTPException wrappers and handler for problem+json.
python/src/jentic/problem_details/models.py Implements Pydantic ProblemDetail and ErrorItem models.
python/src/jentic/problem_details/__init__.py Exposes public Python package API and sets __version__.
python/src/jentic/__init__.py Adds jentic namespace package marker.
python/README.md Adds Python package documentation and usage examples.
python/pyproject.toml Adds Python package metadata, dependencies, and pytest config.
python/.gitignore Adds Python-package specific ignores.
NOTICE Adds attribution/notice content for the repository.
LICENSE Adds Apache 2.0 license text at repository root.
.gitignore Adds repository-wide ignore rules (Python + Node + tooling).
.github/workflows/release.yaml Adds manual release workflow for tagging and publishing to PyPI/NPM.
.github/workflows/ci.yaml Adds CI workflow to run Python + TypeScript build/tests.
Files not reviewed (1)
  • typescript/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread python/src/jentic/problem_details/__init__.py Outdated
Comment thread python/pyproject.toml
Comment thread python/README.md Outdated
Comment thread typescript/tests/schema-conformance.test.ts Outdated
Comment thread typescript/src/errors.ts
Comment thread README.md Outdated
Comment thread .github/workflows/release.yaml
Comment thread python/src/jentic/problem_details/models.py Outdated
Comment thread typescript/tests/schema-conformance.test.ts
Copy link
Copy Markdown
Member

@char0n char0n left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consolidated Review (manual + Copilot)

Good work overall — the architecture is clean, schema conformance tests are a strong design choice, and the ProblemDetailError.fromResponse() ergonomic is nice for frontend consumers. There are several issues to resolve before merge, organized by severity.


🔴 Critical (must fix)

C1. Python package crashes on import without FastAPI installed
python/src/jentic/problem_details/__init__.py unconditionally imports from responses.py, which does from fastapi import HTTPException, Request at the top level. But FastAPI is an optional dependency in pyproject.toml. Any user who installs pip install jentic-problem-details (without [fastapi]) will get ImportError on from jentic.problem_details import ProblemDetail.
Fix: Wrap the responses imports in try/except ImportError and conditionally extend __all__, as Copilot suggested.
(Flagged by both reviewers)

C2. License mismatch: Python says MIT, repo is Apache 2.0

  • python/pyproject.tomllicense = {text = "MIT"} + MIT classifier
  • python/README.md → "MIT"
  • Root LICENSE → Apache 2.0
  • openapi-domain.yaml → Apache 2.0
  • typescript/package.json → Apache-2.0

This is a legal inconsistency that must be resolved before publishing to PyPI.
(Flagged by both reviewers)


🟠 Major (should fix)

M1. __dirname used in ESM context (TypeScript schema conformance tests)
typescript/tests/schema-conformance.test.ts uses __dirname to locate schema files, but the package is ESM ("type": "module"). __dirname is not defined in ESM. This will throw at runtime.
Fix: Use import.meta.url with fileURLToPath/dirname from node:url/node:path.
(Flagged by Copilot)

M2. ProblemDetailError.fromResponse() doesn't handle malformed JSON
typescript/src/errors.ts — When the content-type is application/problem+json, response.json() is called without a try/catch. If the body is empty or malformed (common with proxies/CDNs), this throws an unhandled error instead of falling back to the text-based path.
Fix: Wrap the JSON parse in try/catch, fall back to text/status-based ProblemDetail.
(Flagged by Copilot)

M3. ValidationError title deviates from RFC 9457 convention
Both Python (responses.pytitle="Validation Error") and TypeScript (errors.tstitle: 'Validation Error') use a non-standard title for 422. The OpenAPI spec in openapi-domain.yaml:214 uses title: Unprocessable Content, which is the standard HTTP phrase per RFC 9110. Per RFC 9457, when type is about:blank, title SHOULD be the standard phrase.
(Flagged by manual review)

M4. isProblemDetail and isErrorItem type guards are indistinguishable
typescript/src/types.ts — Both functions check for the exact same condition (typeof obj === 'object' && obj !== null && 'detail' in obj && typeof detail === 'string'). Since both types share detail as their only required field, isProblemDetail returns true for any ErrorItem and vice versa. Consider checking for a distinguishing property (e.g., status or title for ProblemDetail, pointer/parameter/header for ErrorItem), or document this limitation.
(Flagged by manual review)

M5. Unused HttpUrl import in Python models
python/src/jentic/problem_details/models.py:4 imports HttpUrl from Pydantic but never uses it.
(Flagged by both reviewers)

M6. ajv imported but unused in TypeScript schema conformance tests
typescript/tests/schema-conformance.test.ts imports and instantiates Ajv but never uses it. Either use it for actual JSON Schema validation or remove the import and the ajv devDependency.
(Flagged by both reviewers)

M7. Hand-rolled YAML parser is fragile
typescript/tests/schema-conformance.test.ts — The parseYamlSchema function is a regex-based YAML parser that handles a narrow subset. It will silently produce wrong results if the schema YAML format changes. Consider adding js-yaml as a devDependency (as the Python tests do with pyyaml).
(Flagged by manual review)


🟡 Minor (nice to fix)

m1. __version__ in __init__.py will drift after first release
.github/workflows/release.yaml updates pyproject.toml version but not __init__.py's __version__ = "1.0.0". Consider sourcing __version__ from importlib.metadata at runtime.
(Flagged by both reviewers)

m2. README FastAPI example missing Request import
The root README.md FastAPI example uses Request as a type annotation but only imports FastAPI. Should be from fastapi import FastAPI, Request.
(Flagged by Copilot)

m3. ValidationError name shadows Pydantic's ValidationError
Users who import both from pydantic import ValidationError and from jentic.problem_details import ValidationError will get a conflict. Consider renaming to UnprocessableContent to match the HTTP phrase, which also fixes M3.
(Flagged by manual review)

m4. Release workflow sed version update is fragile
sed -i 's/^version = .*/version = "..."/' pyproject.toml could match unintended lines. Consider a more targeted tool.
(Flagged by manual review)

m5. Release workflow pushes directly to main
git push origin main --tags bypasses branch protection. Consider whether this is intentional.
(Flagged by manual review)

m6. Duplicate .gitignore patterns
python/.gitignore duplicates most Python patterns already in the root .gitignore.
(Flagged by manual review)

m7. Missing py.typed marker
Add py.typed to python/src/jentic/problem_details/ so type checkers recognize the package as PEP 561 typed.
(Flagged by manual review)

char0n and others added 12 commits April 13, 2026 17:20
The responses module imports FastAPI at the top level, but FastAPI is
declared as an optional dependency in pyproject.toml. Wrap the import
in try/except ImportError so the package can be imported without
FastAPI installed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Python pyproject.toml and README declared MIT license while the repo
root LICENSE, openapi-domain.yaml, and TypeScript package all use
Apache 2.0. Align Python metadata and classifiers to Apache-2.0.
Also add verbose license section to both Python and TypeScript READMEs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… ajv

Replace __dirname (not available in ESM) with import.meta.url +
fileURLToPath/dirname. Remove unused Ajv import and instantiation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onse

Wrap response.json() in try/catch so that empty or malformed bodies
with application/problem+json content-type fall back to the
text/status-based ProblemDetail instead of throwing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per RFC 9457, when type is "about:blank" the title SHOULD be the
standard HTTP status phrase. RFC 9110 defines 422 as "Unprocessable
Content". Align both Python and TypeScript packages with the OpenAPI
spec in this repo which already uses the correct phrase.
…uards

Both type guards previously checked the same condition (has string
detail field), making them indistinguishable at runtime.
isProblemDetail now requires status or title. isErrorItem checks for
pointer/parameter/header or absence of ProblemDetail-specific fields.
The regex-based YAML parser was fragile and could silently produce
wrong results if the schema format changed. Replace with the yaml
package for reliable parsing. Also remove unused ajv devDependency.
Use importlib.metadata instead of hardcoding version so it stays in
sync with pyproject.toml across releases.
All patterns are already covered by the root .gitignore.
Allows type checkers (mypy, pyright) to recognize this package as
providing inline type information.
@char0n char0n merged commit 9d16794 into main Apr 13, 2026
4 checks passed
@char0n char0n deleted the feat/model-implementation branch April 13, 2026 16:01
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants