Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion .github/renovate.json5
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: ["config:recommended"],
// Workflows pin every action to a commit SHA with a `# vX.Y.Z` comment;
// this keeps the pins (and their comments) up to date.
extends: ["config:recommended", "helpers:pinGitHubActionDigests"],
dependencyDashboard: true,
semanticCommits: "enabled",
semanticCommitType: "chore",
Expand Down Expand Up @@ -43,6 +45,33 @@
automerge: false,
labels: ["dependencies", "major-update"],
},
{
// Actions are pinned to commit SHAs, and non-major updates automerge
// (rule above). Without a delay, a compromised upstream release would be
// merged as soon as CI passes, including the PyPI publish action that
// release.yml runs. This holds each update until its release is 3 days
// old; automerge still applies after that.
//
// github-actions updates come from the `github-tags` datasource, which
// provides a release timestamp: the committedDate of the commit the
// matched tag points to. Digest updates are aged against the newest
// matching version's timestamp. `timestamp-required` (the default since
// Renovate 42, set explicitly here) keeps an update without a timestamp
// pending instead of letting it through immediately. `strict` (also the
// default) creates no branch until the age check passes. Pending
// updates are listed on the Dependency Dashboard, where they can be
// forced.
//
// Limitation: committedDate is set by whoever made the commit, and a
// tag that is force-pushed is aged against the original date. So this
// is a delay for ordinary releases, not a guarantee against a
// determined attacker.
description: "Wait 3 days before raising (and automerging) GitHub Actions updates",
matchManagers: ["github-actions"],
minimumReleaseAge: "3 days",
minimumReleaseAgeBehaviour: "timestamp-required",
internalChecksFilter: "strict",
},
{
description: "lowest.yml pins the oldest supported Python on purpose",
matchFileNames: [".github/workflows/lowest.yml"],
Expand Down
23 changes: 15 additions & 8 deletions .github/workflows/coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,17 @@ jobs:
- 6379:6379

steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Sync dependencies
run: uv sync
Expand All @@ -67,7 +69,7 @@ jobs:

- name: Keep the badge for the deploy job
if: github.event_name == 'push'
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-badge
path: coverage.svg
Expand All @@ -91,17 +93,22 @@ jobs:
cancel-in-progress: false

steps:
# The deploy action runs git in the workspace, so it needs a checkout.
- uses: actions/checkout@v7
# The deploy action runs git in the workspace, so it needs a checkout. It
# does not need the checkout's credentials: it drops the checkout's auth
# header and pushes to a remote URL built from its own `token` input
# (the job's GITHUB_TOKEN by default).
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Download coverage badge
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: coverage-badge
path: badge

- name: Upload coverage badge
uses: JamesIves/github-pages-deploy-action@v4
uses: JamesIves/github-pages-deploy-action@fa24774553152dd7873cd16ebd8d959b010c5445 # v4.9.0
with:
branch: coverage-badge
# Only the badge. `clean` removes what earlier deploys left there:
Expand Down
11 changes: 8 additions & 3 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,25 @@ on:
- 'uv.lock'
- '.github/workflows/docs.yml'

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

# Same command Read the Docs runs; a broken link or docstring reference
# fails the PR here instead of the published site.
Expand Down
11 changes: 8 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,25 @@ on:
pull_request:
branches: [ "master" ]

permissions:
contents: read

jobs:
lint:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Sync dependencies
run: uv sync --group dev --extra jwt
Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/lowest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,19 @@ jobs:
- 6379:6379

steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
# The oldest supported Python. Renovate leaves it alone (see
# .github/renovate.json5).
python-version: "3.10"

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Sync dependencies
run: uv sync
Expand Down
21 changes: 11 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,19 @@ jobs:
echo "::error::Releases run from refs/heads/master only, not $REF. Tick dry run to rehearse elsewhere." >&2
exit 1

- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # Tags, for the "already released" check below
# This job runs every dev dependency; leave it no git credentials.
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14"

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

# The extras are redundant — the dev group already pins redis, pymemcache,
# PyJWT and orjson — but they are named anyway. This is the one job where
Expand Down Expand Up @@ -255,7 +255,7 @@ jobs:
# carries, the notes and `dist/`, exactly as this job produced them, so
# nothing after the gate builds or bumps anything a second time.
- name: Upload the release files
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-v${{ steps.version.outputs.version }}
path: |
Expand Down Expand Up @@ -285,13 +285,14 @@ jobs:
steps:
# The same commit `build` checked out and tested: both default to
# `github.sha`. If master has moved since, the push below is rejected as
# a non-fast-forward and nothing is tagged.
- uses: actions/checkout@v7
# a non-fast-forward and nothing is tagged. This checkout keeps its
# credentials: the steps below push with git.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

# Overwrites pyproject.toml, uv.lock and CHANGELOG.md with the bumped
# and promoted copies, and adds release-notes.md and dist/.
- name: Download the release files
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-v${{ needs.build.outputs.version }}

Expand Down Expand Up @@ -322,7 +323,7 @@ jobs:
git push origin "refs/tags/v$VERSION"

- name: Create GitHub Release
uses: softprops/action-gh-release@v3
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
tag_name: v${{ needs.build.outputs.version }}
name: v${{ needs.build.outputs.version }}
Expand All @@ -348,12 +349,12 @@ jobs:

steps:
- name: Download the release files
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-v${{ needs.build.outputs.version }}

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2

- name: Summary
env:
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/renovate-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,20 @@ on:
- '.github/renovate.json5'
- '.github/workflows/renovate-validate.yml'

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Node.js
uses: actions/setup-node@v7
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24

Expand Down
8 changes: 5 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,17 @@ jobs:
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]

steps:
- uses: actions/checkout@v7
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v7
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v10.2.0
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0

- name: Sync dependencies
run: uv sync --extra jwt
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ async def report(cache: AppCache):
- [Distributed lock](https://fastapi-cachex.readthedocs.io/en/latest/LOCK/) — `CacheLock` for multi-process mutual exclusion
- [Runnable examples](https://github.com/allen0099/FastAPI-CacheX/tree/master/examples) — one complete app per feature, each covered by the test suite
- [API reference](https://fastapi-cachex.readthedocs.io/en/latest/api/http-caching/)
- [Development guide](https://fastapi-cachex.readthedocs.io/en/latest/DEVELOPMENT/) and [contributing](https://fastapi-cachex.readthedocs.io/en/latest/CONTRIBUTING/)
- [Development guide](https://fastapi-cachex.readthedocs.io/en/latest/DEVELOPMENT/) and [contributing](https://fastapi-cachex.readthedocs.io/en/latest/CONTRIBUTING/) · [Security policy](https://github.com/allen0099/FastAPI-CacheX/blob/master/SECURITY.md) — report vulnerabilities privately, not in public issues
- [Changelog](https://github.com/allen0099/FastAPI-CacheX/blob/master/CHANGELOG.md) · [Known limitations and planned work](https://github.com/allen0099/FastAPI-CacheX/issues)

## License
Expand Down
58 changes: 58 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Security Policy

## Supported versions

Security fixes are released for the latest 0.3.x release line only. Upgrade
to the newest 0.3.x release before reporting, and check whether the problem is
still there.

| Version | Supported |
|--------------------------|-----------|
| Latest 0.3.x (now 0.3.8) | Yes |
| Any older release | No |

A fix ships as a new 0.3.x patch release; earlier releases are not patched.

## Reporting a vulnerability

Please do **not** open a public issue, pull request or discussion for a
security problem. Report it privately through GitHub's private vulnerability
reporting instead:

<https://github.com/allen0099/FastAPI-CacheX/security/advisories/new>

The report is visible only to you and the maintainers until an advisory is
published.

Examples of what counts: a way to forge, reuse or steal a session or OAuth
state token, to read or poison another client's cached response, or to make
the library leak data it was given to protect. A bug in your own application's
use of the library, or in a dependency that FastAPI-CacheX does not work around,
is usually better reported to that project.

## What to include

The more of these a report has, the faster it can be confirmed:

- The FastAPI-CacheX version, the Python version, and the backend in use
(memory, Redis or Memcached) with its server version.
- The affected component, for example `@cache`, `CacheManager`, the session
middleware, `StateManager` or `CacheLock`, and the relevant configuration.
- Steps to reproduce, ideally a minimal FastAPI app or test case.
- What an attacker can achieve, and under which conditions.
- Any fix or mitigation you have in mind.

## What to expect

FastAPI-CacheX is maintained by volunteers in their spare time, so there are no
guaranteed response times. What you can expect:

- An acknowledgement once a maintainer has read the report, and a follow-up
after it has been looked into, saying whether it is being treated as a
vulnerability.
- If it is, a fix in a new 0.3.x patch release, followed by a published GitHub
security advisory that credits you, unless you prefer not to be named.
- Questions in the advisory thread if the report needs more detail.

Please give the maintainers a reasonable chance to release a fix before
disclosing the problem publicly.
5 changes: 5 additions & 0 deletions changelog.d/300.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
**Added a security policy.** `SECURITY.md` explains how to report a
vulnerability privately through GitHub private vulnerability reporting instead
of a public issue, which release line gets security fixes (the latest 0.3.x)
and what to include in a report. It is linked from the contributing guide and
the README.
8 changes: 8 additions & 0 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ We love your input! We want to make contributing to FastAPI-CacheX as easy and t
- Proposing new features
- Becoming a maintainer

## Reporting a Security Vulnerability

Please do not report security problems in public issues or pull requests.
Report them privately through
[GitHub private vulnerability reporting](https://github.com/allen0099/FastAPI-CacheX/security/advisories/new)
instead. The [security policy](https://github.com/allen0099/FastAPI-CacheX/blob/master/SECURITY.md)
lists the supported versions and what to include in a report.

## Development Process

1. Fork the project
Expand Down
4 changes: 4 additions & 0 deletions i18n/zh-TW/docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
- 提議新功能
- 成為維護者

## 回報安全性漏洞 {#reporting-a-security-vulnerability}

請不要在公開的 issue 或 Pull Request 中回報安全性問題,而是透過 [GitHub 私下漏洞回報](https://github.com/allen0099/FastAPI-CacheX/security/advisories/new)私下回報。支援的版本以及回報應包含的內容,請見[安全性政策](https://github.com/allen0099/FastAPI-CacheX/blob/master/SECURITY.md)(英文)。

## 開發流程 {#development-process}

1. Fork 這個專案
Expand Down
Loading
Loading