Skip to content

fix: Require canonical origin for Docker builds - #43

Open
astandrik wants to merge 10 commits into
mainfrom
codex/issue-42-canonical-origin
Open

astandrik wants to merge 10 commits into
mainfrom
codex/issue-42-canonical-origin

Conversation

@astandrik

@astandrik astandrik commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Docker builds could embed http://localhost:3000 in public Markdown, discovery endpoints and HTML metadata even when the container had the correct runtime URL.

Require and validate NEXT_PUBLIC_APP_URL and its matching NEXT_PUBLIC_BASE_PATH before the image build. Propagate both values into the runner and reject invalid or different runtime configuration before next start. Local development keeps its localhost fallback.

Includes URL/base-path regression tests, a production-image smoke test and deployment documentation. The HTML smoke checks the actual canonical, OpenGraph and pet CreativeWork.url values, including negative fixtures with a correct URL elsewhere in the HTML or another JSON-LD object.

The smoke rejects localhost:3000 and the temporary container origin in every checked body and Link header, requires the expected origin/base path in each body, validates Link targets, and compares the three named HTML metadata URLs. It does not exhaustively validate every application-owned URL field inside every document.

The configuration scope is image consistency and the explicitly documented address checks. DNS resolution and network reachability are deployment checks; a complete special-use IP classification policy is outside this PR.

Fixes #42

Verification

  • npm test -- --maxWorkers=1: 1171 passed, 1 skipped.
  • npm run lint, npx tsc --noEmit --incremental false and git diff --check passed.
  • Latest JSON-LD fix: five new rejection cases failed before the change and pass after it. All 15 HTML metadata tests and 78 focused config/runner/base-path/metadata tests pass.
  • npm run test:production-origin: all nine canonical-origin surfaces passed, including pet JSON-LD; a valid but different runtime origin was rejected before Next.js started. The unique container and image were independently verified removed.

Current main (2b036e1) is integrated. No dependency or lockfile changes relative to main; the HTML checker uses the existing jsdom dependency.

Copilot AI lite review requested due to automatic review settings August 14, 2026 14:45
Comment thread scripts/public-origin-image-smoke.mjs Fixed

Copilot AI left a comment

Copy link
Copy Markdown

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 enforces a canonical public origin/base-path contract for Docker production builds to prevent localhost:3000 from being embedded into server-generated absolute URLs (fixing #42). It introduces build- and start-time validation for NEXT_PUBLIC_APP_URL/NEXT_PUBLIC_BASE_PATH, adds targeted contract tests, and includes a Docker image smoke test that verifies multiple “public origin” surfaces.

Changes:

  • Add validate:public-build validation (script + tests) and run it before next build and before Docker next start.
  • Update Dockerfile to require/propagate NEXT_PUBLIC_APP_URL + NEXT_PUBLIC_BASE_PATH as build args and validate them in builder/runner stages.
  • Add a production-image smoke test that builds/runs a container and asserts canonical-origin output across key endpoints; update docs and runtime env examples accordingly.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/lib/base-path.test.ts Adds coverage for localhost fallback behavior in development when NEXT_PUBLIC_APP_URL is unset.
scripts/validate-public-build-config.mjs Implements validation rules for canonical origin/base-path build configuration.
scripts/validate-public-build-config.d.mts Provides TypeScript type declarations for the public build config validator.
scripts/public-build-config.test.mts Adds unit tests covering validator acceptance/rejection cases.
Dockerfile Removes localhost defaults and enforces validated build args before build and before start in the runner image.
package.json Adds validate:public-build, start:docker, and test:production-origin scripts.
scripts/runner-image-contract.test.mts Adds contract assertions for Dockerfile/script wiring and ensures dockerignore excludes local scratch/worktree dirs.
scripts/public-origin-image-smoke.mjs Adds an end-to-end Docker build/run smoke test for canonical-origin output across multiple endpoints.
README.md Documents the Docker build-time origin/base-path contract and how to build images for subpath or subdomain deployments.
DEPLOYMENT.md Clarifies build-time-only nature of the public origin/base-path and removes runtime env guidance for those variables.
deploy/app-session.env.runtime.example Removes public origin/base-path from runtime env template and documents rebuild requirement.
.dockerignore Excludes .scratch and .worktrees from Docker build context.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread scripts/validate-public-build-config.mjs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 32a0566448

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate-public-build-config.mjs Outdated
Comment thread Dockerfile
@astandrik
astandrik force-pushed the codex/issue-42-canonical-origin branch from 32a0566 to 8bbf3aa Compare August 14, 2026 15:06
@astandrik astandrik changed the title Require canonical origin for Docker builds fix: Require canonical origin for Docker builds Aug 14, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8bbf3aa9c8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate-public-build-config.mjs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 02706d613c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/public-origin-image-smoke.mjs
Comment thread scripts/validate-public-build-config.mjs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (1)

scripts/validate-public-build-config.mjs:11

  • NEXT_PUBLIC_BASE_PATH values made only of slashes (for example //) normalize to "/" here, so the validator accepts them when the URL pathname is /. The application normalizer instead treats that result as an empty base path (src/lib/base-path.ts:7-8), while next.config.ts would pass / as Next's basePath. Normalize the computed root path to "" here as well so validation and the build use a consistent contract.
  return `/${trimmed.replace(/^\/+|\/+$/g, "")}`;

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef29477624

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate-public-build-config.mjs

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 5, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-05T17:44:53.233551Z 2fbc803 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3810049a57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate-public-build-config.mjs
Comment thread scripts/public-origin-image-smoke.mjs Outdated
Comment thread scripts/validate-public-build-config.mjs
Comment thread scripts/public-origin-image-smoke.test.mjs Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 227defc9ea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/public-origin-image-smoke.mjs Outdated
Comment thread scripts/public-origin-image-smoke.mjs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c87cf3cee4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +108 to +110
const hostname = normalizeHostname(appUrl.hostname);
if (!hostname) {
throw invalidConfig("NEXT_PUBLIC_APP_URL must contain a nonempty hostname.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject invalid DNS host labels

When NEXT_PUBLIC_APP_URL uses a syntactically invalid public hostname such as https://-example.com, https://example-.com, or https://a..b, the WHATWG URL parser accepts it and this check passes because the normalized hostname is merely nonempty. The Docker build then succeeds and bakes an unusable canonical origin into metadata and discovery responses; validate domain labels for empty components and invalid leading/trailing hyphens after normalization.

Useful? React with 👍 / 👎.

Comment thread scripts/validate-public-build-config.mjs
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.

Production Markdown routes emit localhost:3000 absolute URLs

3 participants