Skip to content

Bring the remaining docs up to date - #71

Open
Joker666 wants to merge 2 commits into
fix/quality-precedencefrom
docs/release-notes
Open

Bring the remaining docs up to date#71
Joker666 wants to merge 2 commits into
fix/quality-precedencefrom
docs/release-notes

Conversation

@Joker666

@Joker666 Joker666 commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Stack (merge bottom-up)

  1. Restructure processing and service, and close the geometry compatibility gaps #66 Restructure processing and service, and close the geometry compatibility gaps
  2. Process animated sources frame by frame #67 Process animated sources frame by frame
  3. Add the imgproxy delivery layer #68 Add the imgproxy delivery layer
  4. Build the image on Debian trixie for libvips 8.16 #69 Build the image on Debian trixie for libvips 8.16
  5. Correct quality precedence and cache-hit header consistency #70 Correct quality precedence and cache-hit header consistency
  6. Bring the remaining docs up to date #71 Bring the remaining docs up to date
  7. Let width and height fill in a resize the type created #72 Let width and height fill in a resize the type created
  8. Close the roadmap's remaining known gaps #73 Close the roadmap's remaining known gaps
  9. Implement the Pro options that were only ever cheap #74 Implement the Pro options that were only ever cheap
  10. Run the pipeline in imgproxy's stage order #75 Run the pipeline in imgproxy's stage order

Each PR targets the one before it, so its diff shows only its own change. Together they make up the 0.18.0 release.

Stacked on #70. Documentation only.

  • Request lifecycle gains the negotiation and delivery stages, and the two new response codes (304, and 404 for an expired URL). The stage numbering was renumbered to match the diagram.
  • Caching explains what joins the cache key besides the path — the configured default format, the negotiated format, the effective result ceiling — what a cache hit cannot reproduce (Last-Modified, which comes from the source response), and how the client-side headers relate to the server-side cache.
  • Installation notes that libvips 8.16+ is recommended and lists the libheif codec plugins Debian packages separately.
  • README and introduction state that every option in imgproxy's free tier is implemented.

Cross-checked every IMGFORGE_* variable in the docs against src/constants.rs: no setting is undocumented, and nothing documented is absent from the code.

Validation

cargo fmt -- --check
cargo clippy --all-targets -- -D warnings
cargo test --all -- --test-threads=1

@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: 673f55eafc

ℹ️ 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 doc/7_caching.md Outdated
- **Key derivation**: the cache key is the full request path — processing options, `cachebuster`, and output format included. Any difference in the path is a different entry. Three things outside the path join it, because each changes the bytes without changing the URL: `IMGFORGE_DEFAULT_FORMAT` for URLs that name no format, the format chosen by content negotiation, and the effective `max_result_dimension`. That last one means lowering the ceiling retires entries stored under a higher one rather than serving an image the limit now forbids.
- **Population**: rendered bytes are inserted after a successful response. A failed write is logged and does not affect the response.
- **Invalidation**: there is no explicit purge. Caches are capacity-limited and evict least-recently-used entries; change the `cachebuster` token to force a miss when an upstream asset changes.
- **What a hit cannot reproduce**: `Last-Modified` comes from the source response, which a hit never makes, so it is absent on cache hits. `Cache-Control`, `ETag`, and the canonical `Link` are all derived from the configuration or the bytes and are identical either way.

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 Describe pass-through Cache-Control as unavailable on hits

When IMGFORGE_CACHE_CONTROL_PASSTHROUGH is enabled and the origin supplies Cache-Control, this header is not identical on cache hits: the miss path builds SourceMetadata from the fetched response, while the hit path in src/service/mod.rs constructs metadata without cache_control, causing response::cache_control to fall back to IMGFORGE_TTL or omit the header. Document Cache-Control alongside Last-Modified as origin data that a hit cannot reproduce, with the configured TTL as the possible fallback.

Useful? React with 👍 / 👎.

@Joker666

Copy link
Copy Markdown
Contributor Author

@codex review

@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: bbbda43679

ℹ️ 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 doc/7_caching.md Outdated
## How caching works

- **Key derivation**: the cache key is the full request path — processing options, `cachebuster`, and output format included. Any difference in the path is a different entry.
- **Key derivation**: the cache key is the full request path — processing options, `cachebuster`, and output format included. Any difference in the path is a different entry. Three things outside the path join it, because each changes the bytes without changing the URL: `IMGFORGE_DEFAULT_FORMAT` for URLs that name no format, the format chosen by content negotiation, and the effective `max_result_dimension`. That last one means lowering the ceiling retires entries stored under a higher one rather than serving an image the limit now forbids.

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 List client hints among the cache-key inputs

When IMGFORGE_ENABLE_CLIENT_HINTS is enabled, identical paths requested with different Width or DPR values produce distinct hint=... cache keys in processed_cache_key; therefore the statement that only three inputs outside the path join the key is incomplete. This omission can mislead operators diagnosing extra entries or invalidation behavior, so document the client-hint dimensions as another cache-key component.

Useful? React with 👍 / 👎.

Comment thread doc/6_request_lifecycle.md Outdated

| Response | Cause |
| ------------------------- | --------------------------------------------------------------------------- |
| `304` | The request's `If-None-Match` matched the response's `ETag`. Requires `IMGFORGE_USE_ETAG`. |

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 Document If-Modified-Since as another 304 path

A 304 does not require IMGFORGE_USE_ETAG: when IMGFORGE_LAST_MODIFIED_ENABLED is enabled and ETags are disabled, image_response compares If-Modified-Since with the delivered Last-Modified value and also returns 304 Not Modified. The current row incorrectly tells users that this status is available only through If-None-Match and ETags.

Useful? React with 👍 / 👎.

Comment thread doc/6_request_lifecycle.md Outdated
On success the bytes are inserted into the cache; a failed write is logged but does not affect the response. imgforge replies `200 OK` with the encoded bytes, the matching `Content-Type`, and an `X-Request-ID` header for log correlation.

## 8. Metrics & logging
The delivery headers are attached here — `Cache-Control`, `ETag`, `Last-Modified`, the canonical `Link`, `Vary: Accept`, and the CORS origin, each when configured. A request whose `If-None-Match` matches the `ETag` gets `304 Not Modified` with no body; the bytes were produced either way, so the saving is bandwidth rather than work.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Include client-hint fields in the Vary description

When client hints are enabled, the response varies on Sec-CH-Width, Width, Sec-CH-DPR, and DPR, and Accept may be absent if format negotiation is disabled. Describing the delivery header specifically as Vary: Accept is therefore inaccurate for that configuration and obscures the dimensions shared caches must distinguish.

Useful? React with 👍 / 👎.

@Joker666
Joker666 force-pushed the docs/release-notes branch from bbbda43 to 3b03c16 Compare August 17, 2026 05:05
@Joker666

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 3b03c16ca9

ℹ️ 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 doc/6_request_lifecycle.md Outdated
├─ 7. populate cache │
├─ 6. fetch source ─── upstream status ──▶ 400
too large / wrong MIME ──▶ 400
├─ 7. transform ────── over IMGFORGE_TIMEOUT ──▶ 408 │

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 Show IMGFORGE_TIMEOUT as request-wide

Move this timeout branch out of the transform-only stage: TimeoutLayer wraps the entire router in src/server.rs, so when IMGFORGE_TIMEOUT is shorter than an origin fetch, cache lookup, watermark fetch, or semaphore wait, the request can return 408 before transformation begins. The current diagram misdirects operators diagnosing a 408 as necessarily caused by image processing.

Useful? React with 👍 / 👎.

Comment thread doc/6_request_lifecycle.md Outdated
├─ 6. transform ────── over IMGFORGE_TIMEOUT ──▶ 408 │
├─ 7. populate cache │
├─ 6. fetch source ─── upstream status ──▶ 400
too large / wrong MIME ──▶ 400

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 Place MIME checks in the stage that performs them

For an ordinary processed request, IMGFORGE_ALLOWED_MIME_TYPES and the resolution constraint are enforced inside the blocking transformation closure, after open_source and after acquiring the worker permit; only raw/pass-through responses check them before returning. Labeling a wrong MIME as a stage-6 fetch failure, reinforced by line 51's stale reference to “the start of stage 6,” gives an incorrect account of when decoding and worker capacity have already been consumed.

Useful? React with 👍 / 👎.

Comment thread doc/7_caching.md Outdated
| `max_animation_frames` | A ceiling is in force. |
| `max_animation_frame_resolution` | A ceiling is in force. |

The three ceilings behave the same way: lowering one retires the entries stored under a higher one rather than serving an image the limit now forbids. A key is left untouched when its input does not apply, so turning any of these on does not invalidate a cache that never used it.

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 Correct the ceiling-enablement invalidation claim

Enabling one of these ceilings does invalidate the previously usable namespace: processed_cache_key prepends mrd=..., maf=..., or mafr=... whenever the corresponding effective limit becomes Some, so an entry written while the limit was unset will no longer be found. This sentence tells operators the opposite of the behavior they will observe after enabling a limit.

Useful? React with 👍 / 👎.

Comment thread ROADMAP.md Outdated
Comment on lines +24 to +26
- **`preserve_hdr` on libvips below 8.16** — the `gainmap` keep flag does not exist there. imgforge checks the
runtime version once and drops the flag on an older build, so the request loses the gain map instead of failing;
the high-bit-depth half of the option still works. The published image ships 8.16.1 and is unaffected.

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 Synchronize the preserve_hdr compatibility documentation

Update the processing-option catalog together with this corrected behavior: doc/5_processing_options.md still says that enabling preserve_hdr on libvips below 8.16 makes encoding fail, while this text and supports_gainmap_flag() show that only the gain map is dropped. Users consulting the primary option reference therefore still receive the obsolete and contradictory compatibility warning.

Useful? React with 👍 / 👎.

│ source not allowed ──▶ 400
├─ 3. cache lookup ─── hit ────────────────────────────┐
├─ 5. cache lookup ─── hit ────────────────────────────┐

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Update the caching guide's renumbered stage reference

Changing cache lookup to stage 5 leaves doc/7_caching.md line 3 pointing readers to stage 3, which is now option parsing. Update that cross-reference as part of this renumbering so the two linked lifecycle descriptions agree.

Useful? React with 👍 / 👎.

@Joker666
Joker666 force-pushed the docs/release-notes branch from 3b03c16 to 2bbafd3 Compare August 21, 2026 03:53
@Joker666

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 2bbafd325c

ℹ️ 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 doc/6_request_lifecycle.md Outdated
`IMGFORGE_MAX_SRC_FILE_SIZE` (or a per-request override) is enforced while the body streams, so an oversized source is abandoned mid-download — that one really does belong to the fetch.

## 5. Option parsing
`IMGFORGE_ALLOWED_MIME_TYPES` and `IMGFORGE_MAX_SRC_RESOLUTION` are checked in stage 7, not stage 6: the resolution check needs the dimensions, so libvips has opened the buffer and a worker slot has already been taken by the time either runs. Treat them as limits on what gets *processed*, not as a barrier in front of the decoder. The exception is `raw` and a matching `skip_processing`, which never enter stage 7 at all — those two run both checks before returning the source bytes, so opting out of processing is not a way around them.

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 Qualify source checks for cached passthroughs

When a raw or matching skip_processing response was cached before IMGFORGE_ALLOWED_MIME_TYPES or IMGFORGE_MAX_SRC_RESOLUTION was tightened, process_path returns the cached bytes at src/service/mod.rs:189-208 without reaching enforce_source_constraints at lines 241-246; neither setting participates in processed_cache_key. Thus these checks do not always run before source bytes are returned, and operators relying on the new limits must purge/change the cache key or wait for eviction.

Useful? React with 👍 / 👎.

@Joker666

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 06620936c0

ℹ️ 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 doc/7_caching.md Outdated

| Input | Joins the key when |
| ----- | ------------------ |
| Output version | Always. Bumped by any release that changes the bytes an unchanged URL produces, so an upgrade retires entries rather than serving the old output indefinitely. |

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 Qualify output-version keying for raw responses

When a cached request uses raw, processed_cache_key returns from the is_raw branch before applying OUTPUT_VERSION, so those entries survive an upgrade; only source-limit prefixes can retire them. Saying the output version joins “Always” and that an upgrade retires entries can therefore mislead operators troubleshooting persistent raw cache entries; document the raw exception.

Useful? React with 👍 / 👎.

@Joker666
Joker666 force-pushed the docs/release-notes branch from 0662093 to 8a2ab16 Compare August 21, 2026 21:13
@Joker666
Joker666 force-pushed the docs/release-notes branch from 8a2ab16 to e46fe1b Compare August 21, 2026 21:44
@Joker666
Joker666 force-pushed the docs/release-notes branch from e46fe1b to f97e34d Compare August 21, 2026 23:44
@Joker666
Joker666 force-pushed the docs/release-notes branch from f97e34d to c12dce3 Compare August 21, 2026 23:53
@Joker666
Joker666 force-pushed the docs/release-notes branch 2 times, most recently from 4c7b48c to a352b26 Compare August 22, 2026 00:19
@Joker666
Joker666 force-pushed the docs/release-notes branch from a352b26 to 915c754 Compare August 22, 2026 00:26
@Joker666
Joker666 force-pushed the docs/release-notes branch from 915c754 to d5ba690 Compare August 22, 2026 00:36
@Joker666
Joker666 force-pushed the docs/release-notes branch from d5ba690 to d4be9ce Compare August 22, 2026 00:43
@Joker666
Joker666 force-pushed the docs/release-notes branch from d4be9ce to c37e4cf Compare August 22, 2026 00:52
@Joker666
Joker666 force-pushed the docs/release-notes branch from c37e4cf to 19ea6e3 Compare August 22, 2026 01:01
@Joker666
Joker666 force-pushed the docs/release-notes branch from 19ea6e3 to c6efeeb Compare August 22, 2026 01:12
Joker666 and others added 2 commits August 21, 2026 21:21
Request lifecycle gains the negotiation and delivery stages and the two
new response codes; caching explains what joins the key besides the path,
what a cache hit cannot reproduce, and how the client-side headers relate
to the server-side cache.
The delivery layer now records the origin's Cache-Control and
Last-Modified with each cache entry and serves them on hits, so the
paragraph describing them as unavailable there described behaviour
that no longer exists.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@Joker666
Joker666 force-pushed the docs/release-notes branch from c6efeeb to 3e1af5b Compare August 22, 2026 01:23
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.

1 participant