Add GET /version endpoint returning version from package.json #15

Open
opened 2026-03-06 10:23:09 +00:00 by jesper · 6 comments
Owner

Specification

Metadata:

  • Repo: /repos/jesper/PingAPI
  • Base ref: main
  • Created: 2026-03-06

Context

PingAPI has no way to report its own version. Operators and monitoring tools need a version endpoint to verify which build is deployed, detect stale deployments, and automate rollout checks.

Goal

Add a GET /version endpoint that reads the version field from package.json and returns it as JSON. This is a new read-only route added to the existing Express server -- no new dependencies, no breaking changes.

Scope

In scope

  • GET /version endpoint returning {"version":""} with status 200
  • Version read from package.json at startup (not on every request)
  • Standard JSON Content-Type header

Out of scope

  • Build metadata (git SHA, build date)
  • Authentication on the version endpoint
  • Dynamic version reloading
  • Caching headers

Requirements

  • GET /version returns {"version":"1.0.0"} (or whatever version is in package.json) with status 200
  • Response Content-Type is application/json
  • Version is read once at startup from package.json, not on every request
  • If package.json has no version field, return {"version":"unknown"}
  • Endpoint is logged by morgan like all other routes

Acceptance Criteria (Gherkin)

Feature: Specification
  Scenario: GET /version returns version from package.json
    Given PingAPI is running with a package.json file containing {"version": "1.0.0"}
    When I send a GET request to "/version"
    Then the response status code should be 200
    And the response body should be '{"version":"1.0.0"}'
    And the Content-Type header should be 'application/json'

  Scenario: GET /version returns "unknown" when version field is missing in package.json
    Given PingAPI is running with a package.json file that does not contain a version field
    When I send a GET request to "/version"
    Then the response status code should be 200
    And the response body should be '{"version":"unknown"}'
    And the Content-Type header should be 'application/json'

  Scenario: GET /version is logged by morgan like all other routes
    Given PingAPI is running and morgan is configured to log requests
    When I send a GET request to "/version"
    Then the morgan logs should include the "/version" endpoint being accessed

Architecture alignment

  • Detected stack: Not detected (repo not accessible)
  • Forbidden paths: .git/, node_modules/, .env, secrets.*, vendor/, pycache/, dist/, build/

Code structure

  • Module pattern: Not detected (no recognized language marker found)
  • File conventions:
  • Import rules:
  • Notes:

Security and compliance

  • Data classification: PUBLIC
  • AuthN/AuthZ: API authentication required - token-based auth (JWT or API keys), validate all requests
  • Logging/Audit: Security event logging - log all auth attempts, authorization decisions, admin actions
  • PII/Secrets: No PII or secrets identified
  • Security constraints: Input validation required; keep dependencies up-to-date and scan for vulnerabilities; implement rate limiting and CORS policy

Test strategy

  • Golden build command: docker compose build
  • Golden test command: docker compose run --rm app pytest

Test layers

  • Integration tests: httpx/supertest — Test API endpoints with request/response validation, test file I/O with temp directories

Scenario mapping

Scenario Layer Framework Suggested location
GET /version returns version from package.json integration httpx/supertest tests/integration/version_test.js
GET /version returns "unknown" when version field is missing in package.json integration httpx/supertest tests/integration/version_test.js
GET /version is logged by morgan like all other routes integration httpx/supertest tests/integration/morgan_logging_test.js

Quality gates

  • All tests pass (zero failures)
  • No new lint warnings (eslint/ruff/clippy depending on stack)
  • Type check passes (tsc --noEmit/mypy/pyright if applicable)
  • Test coverage does not decrease (report but don't block)
  • No hardcoded secrets or credentials in test code

Engineering principles and DoD additions

  • Follow existing PingAPI patterns (Express, morgan)
  • Single-file change to server.js
  • No new dependencies

Definition of Done

  • PR created with changes scoped correctly
  • All required checks green
  • Acceptance criteria satisfied

Definition of Ready

  • Scope in/out defined
  • Gherkin scenarios are present and testable
  • Architecture alignment reviewed and constraints captured
  • Security/compliance reviewed and constraints captured
  • Test strategy defined for each scenario
  • Repo golden commands known or explicitly blocked
  • Allowed/forbidden paths set
  • No blocking questions remain
  • Code structure reviewed
  • Engineering principles captured
  • Fields contain distinct content
  • Sufficient detail provided
# Specification **Metadata:** - Repo: `/repos/jesper/PingAPI` - Base ref: `main` - Created: 2026-03-06 ## Context PingAPI has no way to report its own version. Operators and monitoring tools need a version endpoint to verify which build is deployed, detect stale deployments, and automate rollout checks. ## Goal Add a GET /version endpoint that reads the version field from package.json and returns it as JSON. This is a new read-only route added to the existing Express server -- no new dependencies, no breaking changes. ## Scope ### In scope - GET /version endpoint returning {"version":"<semver>"} with status 200 - Version read from package.json at startup (not on every request) - Standard JSON Content-Type header ### Out of scope - Build metadata (git SHA, build date) - Authentication on the version endpoint - Dynamic version reloading - Caching headers ## Requirements - GET /version returns {"version":"1.0.0"} (or whatever version is in package.json) with status 200 - Response Content-Type is application/json - Version is read once at startup from package.json, not on every request - If package.json has no version field, return {"version":"unknown"} - Endpoint is logged by morgan like all other routes ## Acceptance Criteria (Gherkin) ```gherkin Feature: Specification Scenario: GET /version returns version from package.json Given PingAPI is running with a package.json file containing {"version": "1.0.0"} When I send a GET request to "/version" Then the response status code should be 200 And the response body should be '{"version":"1.0.0"}' And the Content-Type header should be 'application/json' Scenario: GET /version returns "unknown" when version field is missing in package.json Given PingAPI is running with a package.json file that does not contain a version field When I send a GET request to "/version" Then the response status code should be 200 And the response body should be '{"version":"unknown"}' And the Content-Type header should be 'application/json' Scenario: GET /version is logged by morgan like all other routes Given PingAPI is running and morgan is configured to log requests When I send a GET request to "/version" Then the morgan logs should include the "/version" endpoint being accessed ``` ## Architecture alignment - Detected stack: Not detected (repo not accessible) - Forbidden paths: .git/, node_modules/, .env, secrets.*, vendor/, __pycache__/, dist/, build/ ## Code structure - Module pattern: Not detected (no recognized language marker found) - File conventions: - Import rules: - Notes: ## Security and compliance - Data classification: PUBLIC - AuthN/AuthZ: API authentication required - token-based auth (JWT or API keys), validate all requests - Logging/Audit: Security event logging - log all auth attempts, authorization decisions, admin actions - PII/Secrets: No PII or secrets identified - Security constraints: Input validation required; keep dependencies up-to-date and scan for vulnerabilities; implement rate limiting and CORS policy ## Test strategy - Golden build command: docker compose build - Golden test command: docker compose run --rm app pytest ### Test layers - Integration tests: httpx/supertest — Test API endpoints with request/response validation, test file I/O with temp directories ### Scenario mapping | Scenario | Layer | Framework | Suggested location | |----------|-------|-----------|-------------------| | GET /version returns version from package.json | integration | httpx/supertest | tests/integration/version_test.js | | GET /version returns "unknown" when version field is missing in package.json | integration | httpx/supertest | tests/integration/version_test.js | | GET /version is logged by morgan like all other routes | integration | httpx/supertest | tests/integration/morgan_logging_test.js | ### Quality gates - All tests pass (zero failures) - No new lint warnings (`eslint`/`ruff`/`clippy` depending on stack) - Type check passes (`tsc --noEmit`/`mypy`/`pyright` if applicable) - Test coverage does not decrease (report but don't block) - No hardcoded secrets or credentials in test code ## Engineering principles and DoD additions - Follow existing PingAPI patterns (Express, morgan) - Single-file change to server.js - No new dependencies ## Definition of Done - PR created with changes scoped correctly - All required checks green - Acceptance criteria satisfied ## Definition of Ready - [ ] Scope in/out defined - [ ] Gherkin scenarios are present and testable - [ ] Architecture alignment reviewed and constraints captured - [ ] Security/compliance reviewed and constraints captured - [ ] Test strategy defined for each scenario - [ ] Repo golden commands known or explicitly blocked - [ ] Allowed/forbidden paths set - [ ] No blocking questions remain - [ ] Code structure reviewed - [ ] Engineering principles captured - [ ] Fields contain distinct content - [ ] Sufficient detail provided
Author
Owner

⚠️ Blocking Questions

The refinement pipeline identified blocking questions that need answers before proceeding:

Questions (Human in the loop)

Blocking questions

  1. Question: What specific problem does "Specification" solve? What is the current state that needs to change?
    Answer:

  2. Question: What are the concrete requirements for "Specification"? List at least 3 specific, verifiable conditions.
    Answer:

  3. Question: What should be in scope vs out of scope for this work? Be specific about deliverables.
    Answer:

  4. Question: What is in scope for this work? Please list specific deliverables.
    Answer:

Notes

  • The spec fields were too thin or duplicated for the pipeline to refine automatically
  • Please provide distinct answers — context (why), goal (what), requirements (how to verify)

Next steps:

  1. Answer the blocking questions by editing this comment or adding a new comment
  2. Run: vault67 answer 15
## ⚠️ Blocking Questions The refinement pipeline identified blocking questions that need answers before proceeding: # Questions (Human in the loop) ## Blocking questions 1) Question: What specific problem does "Specification" solve? What is the current state that needs to change? Answer: 2) Question: What are the concrete requirements for "Specification"? List at least 3 specific, verifiable conditions. Answer: 3) Question: What should be in scope vs out of scope for this work? Be specific about deliverables. Answer: 4) Question: What is in scope for this work? Please list specific deliverables. Answer: ## Notes - The spec fields were too thin or duplicated for the pipeline to refine automatically - Please provide distinct answers — context (why), goal (what), requirements (how to verify) **Next steps:** 1. Answer the blocking questions by editing this comment or adding a new comment 2. Run: `vault67 answer 15`
Author
Owner

Answers Provided

State changed from NEEDS_INFO to REFINING. The refinement pipeline can now re-run.

Next steps:
Run: vault67 refine 15

## ✅ Answers Provided State changed from NEEDS_INFO to REFINING. The refinement pipeline can now re-run. **Next steps:** Run: `vault67 refine 15`
Author
Owner

Ready for Implementation

The specification has passed all refinement criteria.

Promptpack (click to expand)

Implementation Prompt Pack (for Gas Town)

Objective

Add a GET /version endpoint that reads the version field from package.json and returns it as JSON. This is a new read-only route added to the existing Express server -- no new dependencies, no breaking changes.

Context

PingAPI has no way to report its own version. Operators and monitoring tools need a version endpoint to verify which build is deployed, detect stale deployments, and automate rollout checks.

Scope

In scope

  • GET /version endpoint returning {"version":""} with status 200
  • Version read from package.json at startup (not on every request)
  • Standard JSON Content-Type header

Out of scope

  • Build metadata (git SHA, build date)
  • Authentication on the version endpoint
  • Dynamic version reloading
  • Caching headers

Acceptance criteria (Gherkin, must satisfy)

Constraints and guardrails

Architecture alignment

  • Detected stack: Not detected (repo not accessible)
  • Forbidden paths: .git/, node_modules/, .env, secrets.*, vendor/, pycache/, dist/, build/

Code structure guidance

  • Module pattern: Not detected (no recognized language marker found)
  • File conventions:
  • Import rules:
  • Notes:

Security/compliance constraints

  • Data classification: PUBLIC
  • AuthN/AuthZ: API authentication required - token-based auth (JWT or API keys), validate all requests
  • Logging/Audit: Security event logging - log all auth attempts, authorization decisions, admin actions
  • PII/Secrets: No PII or secrets identified
  • Security constraints: Input validation required; keep dependencies up-to-date and scan for vulnerabilities; implement rate limiting and CORS policy

Repo instructions

Base ref

  • main

How to build (golden command)

docker compose build

How to test (golden command)

docker compose run --rm app pytest

Test strategy

  • Golden build command: docker compose build
  • Golden test command: docker compose run --rm app pytest
  • Integration tests: httpx/supertest — Test API endpoints with request/response validation, test file I/O with temp directories
    Scenario Layer Framework Suggested location
    GET /version returns version from package.json integration httpx/supertest tests/integration/version_test.js
    GET /version returns "unknown" when version field is missing in package.json integration httpx/supertest tests/integration/version_test.js
    GET /version is logged by morgan like all other routes integration httpx/supertest tests/integration/morgan_logging_test.js
  • All tests pass (zero failures)
  • No new lint warnings (eslint/ruff/clippy depending on stack)
  • Type check passes (tsc --noEmit/mypy/pyright if applicable)
  • Test coverage does not decrease (report but don't block)
  • No hardcoded secrets or credentials in test code

Verification checklist

  • All tests pass using golden commands
  • Acceptance criteria satisfied
  • Quality gates pass (lint, typecheck — see test strategy)
  • No out-of-scope changes
  • Required docs updated (if applicable)

Expected output

  • Create a PR against base ref
  • Include a brief PR description mapping changes to scenarios
  • Include test results summary

Next steps:
Run: vault67 implement 15

## ✅ Ready for Implementation The specification has passed all refinement criteria. <details> <summary>Promptpack (click to expand)</summary> # Implementation Prompt Pack (for Gas Town) ## Objective Add a GET /version endpoint that reads the version field from package.json and returns it as JSON. This is a new read-only route added to the existing Express server -- no new dependencies, no breaking changes. ## Context PingAPI has no way to report its own version. Operators and monitoring tools need a version endpoint to verify which build is deployed, detect stale deployments, and automate rollout checks. ## Scope ### In scope - GET /version endpoint returning {"version":"<semver>"} with status 200 - Version read from package.json at startup (not on every request) - Standard JSON Content-Type header ### Out of scope - Build metadata (git SHA, build date) - Authentication on the version endpoint - Dynamic version reloading - Caching headers ## Acceptance criteria (Gherkin, must satisfy) ## Constraints and guardrails ### Architecture alignment - Detected stack: Not detected (repo not accessible) - Forbidden paths: .git/, node_modules/, .env, secrets.*, vendor/, __pycache__/, dist/, build/ ### Code structure guidance - Module pattern: Not detected (no recognized language marker found) - File conventions: - Import rules: - Notes: ### Security/compliance constraints - Data classification: PUBLIC - AuthN/AuthZ: API authentication required - token-based auth (JWT or API keys), validate all requests - Logging/Audit: Security event logging - log all auth attempts, authorization decisions, admin actions - PII/Secrets: No PII or secrets identified - Security constraints: Input validation required; keep dependencies up-to-date and scan for vulnerabilities; implement rate limiting and CORS policy ## Repo instructions ### Base ref - main ### How to build (golden command) docker compose build ### How to test (golden command) docker compose run --rm app pytest ## Test strategy - Golden build command: docker compose build - Golden test command: docker compose run --rm app pytest - Integration tests: httpx/supertest — Test API endpoints with request/response validation, test file I/O with temp directories | Scenario | Layer | Framework | Suggested location | |----------|-------|-----------|-------------------| | GET /version returns version from package.json | integration | httpx/supertest | tests/integration/version_test.js | | GET /version returns "unknown" when version field is missing in package.json | integration | httpx/supertest | tests/integration/version_test.js | | GET /version is logged by morgan like all other routes | integration | httpx/supertest | tests/integration/morgan_logging_test.js | - All tests pass (zero failures) - No new lint warnings (`eslint`/`ruff`/`clippy` depending on stack) - Type check passes (`tsc --noEmit`/`mypy`/`pyright` if applicable) - Test coverage does not decrease (report but don't block) - No hardcoded secrets or credentials in test code ## Verification checklist - [ ] All tests pass using golden commands - [ ] Acceptance criteria satisfied - [ ] Quality gates pass (lint, typecheck — see test strategy) - [ ] No out-of-scope changes - [ ] Required docs updated (if applicable) ## Expected output - Create a PR against base ref - Include a brief PR description mapping changes to scenarios - Include test results summary </details> **Next steps:** Run: `vault67 implement 15`
Author
Owner

🚧 Implementation Started

Timestamp: 2026-03-06T10:53:14Z
Executor: gastown
Status: Handed off to Gas Town

Instructions for implementer:

  1. Review the promptpack in the comments above
  2. Implement according to the specification
  3. Create tests as defined in test strategy
  4. Create a PR and link it to this issue
  5. Update issue state when complete

Gas Town handoff:

gt sling --assign <polecat> --work 'Implement: Add GET /version endpoint returning version from package.json (#15)'

Provide the polecat with:

  • Issue URL: #15
  • Promptpack: See comment above
## 🚧 Implementation Started Timestamp: 2026-03-06T10:53:14Z Executor: gastown Status: Handed off to Gas Town **Instructions for implementer:** 1. Review the promptpack in the comments above 2. Implement according to the specification 3. Create tests as defined in test strategy 4. Create a PR and link it to this issue 5. Update issue state when complete **Gas Town handoff:** ```bash gt sling --assign <polecat> --work 'Implement: Add GET /version endpoint returning version from package.json (#15)' ``` Provide the polecat with: - Issue URL: https://git.logikfabriken.se/jesper/PingAPI/issues/15 - Promptpack: See comment above
Author
Owner

🤖 farm33 — Implementation started (worker solo, model: qwen2.5-coder:14b)

🤖 **farm33** — Implementation started (worker solo, model: qwen2.5-coder:14b)
Author
Owner

🤖 farm33 — Implementation pushed as draft PR

Check Result
Spec review FAIL (85/100)
Golden tests FAIL
Acceptance ALL SATISFIED (3 scenarios)
Diff confidence 30/100 (threshold: 70)
Refinement iterations 3/3

Draft PR: #16
Reverting to READY_TO_IMPLEMENT for retry.

🤖 **farm33** — Implementation pushed as draft PR | Check | Result | |-------|--------| | Spec review | FAIL (85/100) | | Golden tests | FAIL | | Acceptance | ALL SATISFIED (3 scenarios) | | Diff confidence | 30/100 (threshold: 70) | | Refinement iterations | 3/3 | Draft PR: https://git.logikfabriken.se/jesper/PingAPI/pulls/16 Reverting to READY_TO_IMPLEMENT for retry.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jesper/PingAPI#15
No description provided.