promptlatch 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- promptlatch-0.2.1/.dockerignore +15 -0
- promptlatch-0.2.1/.github/dependabot.yml +44 -0
- promptlatch-0.2.1/.github/workflows/ci.yml +62 -0
- promptlatch-0.2.1/.github/workflows/codeql.yml +32 -0
- promptlatch-0.2.1/.github/workflows/dependency-review.yml +21 -0
- promptlatch-0.2.1/.github/workflows/release.yml +168 -0
- promptlatch-0.2.1/.gitignore +16 -0
- promptlatch-0.2.1/AGENTS.md +15 -0
- promptlatch-0.2.1/AGENTS_DEPLOY.md +48 -0
- promptlatch-0.2.1/AGENTS_MONITOR.md +39 -0
- promptlatch-0.2.1/AGENTS_TESTING.md +31 -0
- promptlatch-0.2.1/CONTRIBUTING.md +70 -0
- promptlatch-0.2.1/Dockerfile +20 -0
- promptlatch-0.2.1/LICENSE +21 -0
- promptlatch-0.2.1/PKG-INFO +767 -0
- promptlatch-0.2.1/PROMPT.md +161 -0
- promptlatch-0.2.1/README.md +729 -0
- promptlatch-0.2.1/SECURITY.md +40 -0
- promptlatch-0.2.1/SECURITY_AUDIT.md +32 -0
- promptlatch-0.2.1/charts/promptlatch/Chart.yaml +7 -0
- promptlatch-0.2.1/charts/promptlatch/templates/_helpers.tpl +53 -0
- promptlatch-0.2.1/charts/promptlatch/templates/deployment.yaml +69 -0
- promptlatch-0.2.1/charts/promptlatch/templates/secret.yaml +16 -0
- promptlatch-0.2.1/charts/promptlatch/templates/service.yaml +15 -0
- promptlatch-0.2.1/charts/promptlatch/values.yaml +51 -0
- promptlatch-0.2.1/docker-compose.yml +8 -0
- promptlatch-0.2.1/examples/codex-openrouter-promptlatch.config.toml +12 -0
- promptlatch-0.2.1/examples/opencode-openrouter-promptlatch.json +22 -0
- promptlatch-0.2.1/examples/promptlatch-openrouter.config.yaml +33 -0
- promptlatch-0.2.1/pyproject.toml +72 -0
- promptlatch-0.2.1/scripts/audit_secrets.py +181 -0
- promptlatch-0.2.1/scripts/check_helm.py +96 -0
- promptlatch-0.2.1/scripts/check_release.py +125 -0
- promptlatch-0.2.1/site/PROMPT.md +161 -0
- promptlatch-0.2.1/site/favicon.svg +5 -0
- promptlatch-0.2.1/site/hero.png +0 -0
- promptlatch-0.2.1/site/highlight.js +101 -0
- promptlatch-0.2.1/site/icons/LICENSE-lobe-icons.txt +21 -0
- promptlatch-0.2.1/site/icons/LICENSE-lucide.txt +43 -0
- promptlatch-0.2.1/site/icons/LICENSE-simple-icons.md +30 -0
- promptlatch-0.2.1/site/icons/NOTICE.md +13 -0
- promptlatch-0.2.1/site/icons/anthropic.svg +1 -0
- promptlatch-0.2.1/site/icons/atlassian.svg +1 -0
- promptlatch-0.2.1/site/icons/aws.svg +1 -0
- promptlatch-0.2.1/site/icons/check.svg +15 -0
- promptlatch-0.2.1/site/icons/cloudflare.svg +1 -0
- promptlatch-0.2.1/site/icons/codex.svg +1 -0
- promptlatch-0.2.1/site/icons/copy.svg +16 -0
- promptlatch-0.2.1/site/icons/deepseek.svg +1 -0
- promptlatch-0.2.1/site/icons/file-key-2.svg +19 -0
- promptlatch-0.2.1/site/icons/fireworks.svg +1 -0
- promptlatch-0.2.1/site/icons/gemini.svg +1 -0
- promptlatch-0.2.1/site/icons/github.svg +1 -0
- promptlatch-0.2.1/site/icons/hash.svg +18 -0
- promptlatch-0.2.1/site/icons/jwt.svg +1 -0
- promptlatch-0.2.1/site/icons/key-round.svg +16 -0
- promptlatch-0.2.1/site/icons/link-2.svg +17 -0
- promptlatch-0.2.1/site/icons/minimax.svg +1 -0
- promptlatch-0.2.1/site/icons/openai.svg +1 -0
- promptlatch-0.2.1/site/icons/openrouter.svg +1 -0
- promptlatch-0.2.1/site/icons/regex.svg +18 -0
- promptlatch-0.2.1/site/icons/stripe.svg +1 -0
- promptlatch-0.2.1/site/icons/xai.svg +1 -0
- promptlatch-0.2.1/site/icons/zai.svg +1 -0
- promptlatch-0.2.1/site/index.html +466 -0
- promptlatch-0.2.1/site/prompt.js +29 -0
- promptlatch-0.2.1/site/styles.css +559 -0
- promptlatch-0.2.1/src/promptcloak/__init__.py +40 -0
- promptlatch-0.2.1/src/promptcloak/asgi.py +3 -0
- promptlatch-0.2.1/src/promptcloak/audit.py +1 -0
- promptlatch-0.2.1/src/promptcloak/cli.py +3 -0
- promptlatch-0.2.1/src/promptcloak/compat.py +1 -0
- promptlatch-0.2.1/src/promptcloak/config.py +1 -0
- promptlatch-0.2.1/src/promptcloak/library.py +1 -0
- promptlatch-0.2.1/src/promptcloak/patterns.py +1 -0
- promptlatch-0.2.1/src/promptcloak/proxy.py +3 -0
- promptlatch-0.2.1/src/promptcloak/py.typed +1 -0
- promptlatch-0.2.1/src/promptcloak/redaction.py +1 -0
- promptlatch-0.2.1/src/promptcloak/security.py +1 -0
- promptlatch-0.2.1/src/promptcloak/version.py +3 -0
- promptlatch-0.2.1/src/promptlatch/__init__.py +27 -0
- promptlatch-0.2.1/src/promptlatch/asgi.py +3 -0
- promptlatch-0.2.1/src/promptlatch/audit.py +34 -0
- promptlatch-0.2.1/src/promptlatch/cli.py +143 -0
- promptlatch-0.2.1/src/promptlatch/compat.py +486 -0
- promptlatch-0.2.1/src/promptlatch/config.py +343 -0
- promptlatch-0.2.1/src/promptlatch/library.py +148 -0
- promptlatch-0.2.1/src/promptlatch/patterns.py +114 -0
- promptlatch-0.2.1/src/promptlatch/proxy.py +591 -0
- promptlatch-0.2.1/src/promptlatch/py.typed +1 -0
- promptlatch-0.2.1/src/promptlatch/redaction.py +237 -0
- promptlatch-0.2.1/src/promptlatch/security.py +70 -0
- promptlatch-0.2.1/src/promptlatch/version.py +3 -0
- promptlatch-0.2.1/tests/__init__.py +1 -0
- promptlatch-0.2.1/tests/fixtures.py +127 -0
- promptlatch-0.2.1/tests/test_audit.py +18 -0
- promptlatch-0.2.1/tests/test_cli.py +79 -0
- promptlatch-0.2.1/tests/test_compat.py +232 -0
- promptlatch-0.2.1/tests/test_config.py +131 -0
- promptlatch-0.2.1/tests/test_docs.py +70 -0
- promptlatch-0.2.1/tests/test_e2e.py +497 -0
- promptlatch-0.2.1/tests/test_examples.py +55 -0
- promptlatch-0.2.1/tests/test_library.py +119 -0
- promptlatch-0.2.1/tests/test_proxy.py +1271 -0
- promptlatch-0.2.1/tests/test_redaction.py +378 -0
- promptlatch-0.2.1/tests/test_security.py +58 -0
- promptlatch-0.2.1/uv.lock +1277 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: uv
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
versioning-strategy: lockfile-only
|
|
8
|
+
cooldown:
|
|
9
|
+
default-days: 7
|
|
10
|
+
semver-major-days: 30
|
|
11
|
+
semver-minor-days: 7
|
|
12
|
+
semver-patch-days: 3
|
|
13
|
+
groups:
|
|
14
|
+
python-dependencies:
|
|
15
|
+
patterns: ["*"]
|
|
16
|
+
open-pull-requests-limit: 5
|
|
17
|
+
- package-ecosystem: github-actions
|
|
18
|
+
directory: /
|
|
19
|
+
schedule:
|
|
20
|
+
interval: weekly
|
|
21
|
+
cooldown:
|
|
22
|
+
default-days: 7
|
|
23
|
+
semver-major-days: 30
|
|
24
|
+
semver-minor-days: 7
|
|
25
|
+
semver-patch-days: 3
|
|
26
|
+
groups:
|
|
27
|
+
actions:
|
|
28
|
+
patterns: ["*"]
|
|
29
|
+
open-pull-requests-limit: 5
|
|
30
|
+
- package-ecosystem: docker
|
|
31
|
+
directory: /
|
|
32
|
+
schedule:
|
|
33
|
+
interval: weekly
|
|
34
|
+
cooldown:
|
|
35
|
+
default-days: 7
|
|
36
|
+
semver-major-days: 30
|
|
37
|
+
semver-minor-days: 7
|
|
38
|
+
semver-patch-days: 3
|
|
39
|
+
ignore:
|
|
40
|
+
- dependency-name: python
|
|
41
|
+
update-types:
|
|
42
|
+
- version-update:semver-major
|
|
43
|
+
- version-update:semver-minor
|
|
44
|
+
open-pull-requests-limit: 5
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
test:
|
|
17
|
+
name: test (${{ matrix.python-version }})
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.12", "3.13", "3.14"]
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
25
|
+
with:
|
|
26
|
+
fetch-depth: 0
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
29
|
+
- name: Install Python
|
|
30
|
+
env:
|
|
31
|
+
PYTHON_VERSION: ${{ matrix.python-version }}
|
|
32
|
+
run: uv python install "$PYTHON_VERSION"
|
|
33
|
+
- name: Sync environment
|
|
34
|
+
env:
|
|
35
|
+
PYTHON_VERSION: ${{ matrix.python-version }}
|
|
36
|
+
run: uv sync --python "$PYTHON_VERSION" --extra dev --locked
|
|
37
|
+
- run: uv run pytest
|
|
38
|
+
|
|
39
|
+
package:
|
|
40
|
+
name: package
|
|
41
|
+
needs: test
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
45
|
+
with:
|
|
46
|
+
fetch-depth: 0
|
|
47
|
+
persist-credentials: false
|
|
48
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
49
|
+
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
|
|
50
|
+
- run: uv sync --extra dev --group audit --locked
|
|
51
|
+
- run: uv run scripts/check_release.py
|
|
52
|
+
- run: uv run scripts/audit_secrets.py
|
|
53
|
+
- run: uv run ruff check .
|
|
54
|
+
- run: uv run ruff format --check .
|
|
55
|
+
- run: uv run pyright src tests scripts
|
|
56
|
+
- run: uv run pip-audit
|
|
57
|
+
- run: uv build
|
|
58
|
+
- run: helm lint ./charts/promptlatch
|
|
59
|
+
- run: helm template promptlatch ./charts/promptlatch >/dev/null
|
|
60
|
+
- run: uv run scripts/check_helm.py
|
|
61
|
+
- run: docker build -t promptlatch:ci .
|
|
62
|
+
- run: docker run --rm --entrypoint promptlatch promptlatch:ci version
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: codeql
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
schedule:
|
|
8
|
+
- cron: "17 4 * * 1"
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
|
|
13
|
+
concurrency:
|
|
14
|
+
group: codeql-${{ github.workflow }}-${{ github.ref }}
|
|
15
|
+
cancel-in-progress: true
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
analyze:
|
|
19
|
+
name: analyze
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
security-events: write # Upload CodeQL results.
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
persist-credentials: false
|
|
28
|
+
- uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
|
29
|
+
with:
|
|
30
|
+
languages: python
|
|
31
|
+
build-mode: none
|
|
32
|
+
- uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: dependency-review
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
contents: read
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: dependency-review-${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
review:
|
|
15
|
+
name: review
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
|
+
with:
|
|
20
|
+
persist-credentials: false
|
|
21
|
+
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
tag:
|
|
10
|
+
description: Existing release tag to publish
|
|
11
|
+
required: true
|
|
12
|
+
type: string
|
|
13
|
+
|
|
14
|
+
env:
|
|
15
|
+
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
|
|
16
|
+
IMAGE_NAME: ghcr.io/bvolpato/promptlatch
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: release-${{ inputs.tag || github.ref_name }}
|
|
23
|
+
cancel-in-progress: false
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
build:
|
|
27
|
+
name: build
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
permissions:
|
|
30
|
+
attestations: write # Publish provenance for release artifacts.
|
|
31
|
+
contents: read
|
|
32
|
+
id-token: write # Sign provenance through GitHub OIDC.
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
35
|
+
with:
|
|
36
|
+
fetch-depth: 0
|
|
37
|
+
persist-credentials: false
|
|
38
|
+
ref: ${{ env.RELEASE_TAG }}
|
|
39
|
+
- name: Verify release tag
|
|
40
|
+
env:
|
|
41
|
+
GH_TOKEN: ${{ github.token }}
|
|
42
|
+
run: |
|
|
43
|
+
set -euo pipefail
|
|
44
|
+
if [ "$GITHUB_REPOSITORY" != "bvolpato/promptlatch" ]; then
|
|
45
|
+
echo "release must run from bvolpato/promptlatch" >&2
|
|
46
|
+
exit 1
|
|
47
|
+
fi
|
|
48
|
+
ref_json=$(gh api "repos/$GITHUB_REPOSITORY/git/ref/tags/$RELEASE_TAG")
|
|
49
|
+
if [ "$(jq -r '.object.type' <<<"$ref_json")" != "tag" ]; then
|
|
50
|
+
echo "release tag must be annotated and signed" >&2
|
|
51
|
+
exit 1
|
|
52
|
+
fi
|
|
53
|
+
tag_sha=$(jq -r '.object.sha' <<<"$ref_json")
|
|
54
|
+
if [ "$(gh api "repos/$GITHUB_REPOSITORY/git/tags/$tag_sha" --jq '.verification.verified')" != "true" ]; then
|
|
55
|
+
echo "release tag signature is not verified" >&2
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
git fetch --no-tags origin main:refs/remotes/origin/main
|
|
59
|
+
if ! git merge-base --is-ancestor "$RELEASE_TAG^{commit}" origin/main; then
|
|
60
|
+
echo "release tag must point to a commit on main" >&2
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
|
64
|
+
with:
|
|
65
|
+
enable-cache: false
|
|
66
|
+
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
|
|
67
|
+
- run: uv sync --extra dev --group audit --locked
|
|
68
|
+
- run: uv run scripts/check_release.py --tag "$RELEASE_TAG"
|
|
69
|
+
- run: uv run scripts/audit_secrets.py
|
|
70
|
+
- run: uv run ruff check .
|
|
71
|
+
- run: uv run ruff format --check .
|
|
72
|
+
- run: uv run pyright src tests scripts
|
|
73
|
+
- run: uv run pip-audit
|
|
74
|
+
- run: uv run pytest
|
|
75
|
+
- run: uv build
|
|
76
|
+
- run: helm lint ./charts/promptlatch
|
|
77
|
+
- run: helm template promptlatch ./charts/promptlatch >/dev/null
|
|
78
|
+
- run: uv run scripts/check_helm.py
|
|
79
|
+
- run: helm package charts/promptlatch --destination dist
|
|
80
|
+
- run: cd dist && sha256sum -- ./*.whl ./*.tar.gz ./*.tgz > SHA256SUMS
|
|
81
|
+
- uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
|
|
82
|
+
with:
|
|
83
|
+
subject-path: dist/*
|
|
84
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
85
|
+
with:
|
|
86
|
+
name: release-dist
|
|
87
|
+
path: dist/*
|
|
88
|
+
if-no-files-found: error
|
|
89
|
+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
90
|
+
with:
|
|
91
|
+
name: python-dist
|
|
92
|
+
path: |
|
|
93
|
+
dist/*.whl
|
|
94
|
+
dist/*.tar.gz
|
|
95
|
+
if-no-files-found: error
|
|
96
|
+
|
|
97
|
+
publish-pypi:
|
|
98
|
+
name: publish-pypi
|
|
99
|
+
needs: build
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
environment:
|
|
102
|
+
name: pypi
|
|
103
|
+
url: https://pypi.org/p/promptlatch
|
|
104
|
+
permissions:
|
|
105
|
+
id-token: write # Exchange GitHub OIDC identity for a short-lived PyPI token.
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
108
|
+
with:
|
|
109
|
+
name: python-dist
|
|
110
|
+
path: dist
|
|
111
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
112
|
+
|
|
113
|
+
publish:
|
|
114
|
+
name: publish
|
|
115
|
+
needs: build
|
|
116
|
+
runs-on: ubuntu-latest
|
|
117
|
+
permissions:
|
|
118
|
+
contents: write # Create or repair GitHub release assets.
|
|
119
|
+
packages: write # Push versioned GHCR image.
|
|
120
|
+
steps:
|
|
121
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
122
|
+
with:
|
|
123
|
+
fetch-depth: 0
|
|
124
|
+
persist-credentials: false
|
|
125
|
+
ref: ${{ env.RELEASE_TAG }}
|
|
126
|
+
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
|
127
|
+
with:
|
|
128
|
+
name: release-dist
|
|
129
|
+
path: dist
|
|
130
|
+
- uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
|
|
131
|
+
with:
|
|
132
|
+
registry: ghcr.io
|
|
133
|
+
username: ${{ github.actor }}
|
|
134
|
+
password: ${{ github.token }}
|
|
135
|
+
- uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
|
|
136
|
+
- uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
|
|
137
|
+
id: docker-meta
|
|
138
|
+
with:
|
|
139
|
+
images: ${{ env.IMAGE_NAME }}
|
|
140
|
+
tags: |
|
|
141
|
+
type=raw,value=${{ env.RELEASE_TAG }}
|
|
142
|
+
type=semver,pattern={{version}},value=${{ env.RELEASE_TAG }}
|
|
143
|
+
- uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
|
|
144
|
+
with:
|
|
145
|
+
context: .
|
|
146
|
+
provenance: mode=max
|
|
147
|
+
push: true
|
|
148
|
+
sbom: true
|
|
149
|
+
tags: ${{ steps.docker-meta.outputs.tags }}
|
|
150
|
+
labels: ${{ steps.docker-meta.outputs.labels }}
|
|
151
|
+
- name: Publish GitHub release
|
|
152
|
+
env:
|
|
153
|
+
GH_TOKEN: ${{ github.token }}
|
|
154
|
+
run: |
|
|
155
|
+
if gh release view "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then
|
|
156
|
+
gh release upload "$RELEASE_TAG" dist/* \
|
|
157
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
158
|
+
--clobber
|
|
159
|
+
gh release edit "$RELEASE_TAG" \
|
|
160
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
161
|
+
--title "PromptLatch ${RELEASE_TAG#v}"
|
|
162
|
+
else
|
|
163
|
+
gh release create "$RELEASE_TAG" dist/* \
|
|
164
|
+
--repo "$GITHUB_REPOSITORY" \
|
|
165
|
+
--title "PromptLatch ${RELEASE_TAG#v}" \
|
|
166
|
+
--generate-notes \
|
|
167
|
+
--verify-tag
|
|
168
|
+
fi
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Cut verbosity. Use concise, direct status and docs.
|
|
2
|
+
|
|
3
|
+
Rules:
|
|
4
|
+
- Drop articles, filler, pleasantries, hedging.
|
|
5
|
+
- Fragments OK. Technical terms exact. Code blocks unchanged.
|
|
6
|
+
- No em dashes.
|
|
7
|
+
|
|
8
|
+
Python one-off scripts:
|
|
9
|
+
- Use `uv` script metadata.
|
|
10
|
+
- Run with `uv run scripts/name.py`.
|
|
11
|
+
- Do not ask users to install packages globally.
|
|
12
|
+
|
|
13
|
+
Testing:
|
|
14
|
+
- Verify functional changes with tests.
|
|
15
|
+
- Use browser checks for static site changes when practical.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Deploy
|
|
2
|
+
|
|
3
|
+
PromptLatch ships through signed Git tag, GitHub Actions, Homebrew tap, GitHub Pages, and local user service.
|
|
4
|
+
|
|
5
|
+
## Release
|
|
6
|
+
|
|
7
|
+
1. Keep same version in `pyproject.toml`, `src/promptlatch/version.py`, Helm chart metadata, Helm image tag, docs, site, and `uv.lock`.
|
|
8
|
+
2. Run `AGENTS_TESTING.md` checks.
|
|
9
|
+
3. Confirm GitHub repository is `bvolpato/promptlatch`; release workflow rejects any
|
|
10
|
+
other namespace so image and asset URLs cannot diverge.
|
|
11
|
+
4. Commit and push release metadata to `main`.
|
|
12
|
+
5. Wait for `ci` and `codeql` on pushed commit.
|
|
13
|
+
6. Create and push signed tag:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
VERSION=0.2.1
|
|
17
|
+
git tag -s "v${VERSION}" -m "PromptLatch ${VERSION}"
|
|
18
|
+
git push origin "v${VERSION}"
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Tag triggers `.github/workflows/release.yml`. Workflow publishes Python distributions to PyPI,
|
|
22
|
+
GitHub assets, and GHCR image.
|
|
23
|
+
|
|
24
|
+
## Homebrew
|
|
25
|
+
|
|
26
|
+
After release assets exist, update `Formula/promptlatch.rb` in
|
|
27
|
+
`/home/bruno/githubworkspace/homebrew-tap` with release source URL, checksum, and Python
|
|
28
|
+
resources. Reject generated resource versions uploaded less than three days ago; use tested
|
|
29
|
+
`uv.lock` version until cooldown expires. Test formula before signed commit and push.
|
|
30
|
+
|
|
31
|
+
## GitHub Pages
|
|
32
|
+
|
|
33
|
+
Publish exact contents of `site/` to root of `gh-pages`, commit, and push. Pages source is `gh-pages` branch root.
|
|
34
|
+
|
|
35
|
+
## Local service
|
|
36
|
+
|
|
37
|
+
Restart installed source service after release. It listens on `127.0.0.1:8000`:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
systemctl --user restart promptlatch.service
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
OpenCode uses `promptlatch-local` on `127.0.0.1:8787`. Recreate that container from released
|
|
44
|
+
GHCR image with loopback binding, `unless-stopped`, raw-request debug off, and configured target
|
|
45
|
+
base URL matching OpenCode `X-Target-Base-URL`. Keep upstream key in OpenCode header config; do not
|
|
46
|
+
put it in container environment.
|
|
47
|
+
|
|
48
|
+
Never persist or print upstream credentials during deployment checks.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Monitor
|
|
2
|
+
|
|
3
|
+
Verify each published surface after deployment.
|
|
4
|
+
|
|
5
|
+
## GitHub
|
|
6
|
+
|
|
7
|
+
- `ci`, `codeql`, and `release` workflows passed for release commit/tag.
|
|
8
|
+
- Release includes wheel, source archive, Helm chart, and `SHA256SUMS`.
|
|
9
|
+
- Downloaded assets match `SHA256SUMS`; build provenance verifies.
|
|
10
|
+
- Dependabot, secret-scanning, and code-scanning alerts remain empty.
|
|
11
|
+
|
|
12
|
+
## Container and Helm
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
docker pull ghcr.io/bvolpato/promptlatch:0.2.1
|
|
16
|
+
docker run --rm --entrypoint promptlatch ghcr.io/bvolpato/promptlatch:0.2.1 version
|
|
17
|
+
helm lint ./charts/promptlatch
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Homebrew and site
|
|
21
|
+
|
|
22
|
+
- `brew info bvolpato/tap/promptlatch` reports release version.
|
|
23
|
+
- Formula install/test passes.
|
|
24
|
+
- `https://bvolpato.github.io/promptlatch/` matches `site/` and loads assets.
|
|
25
|
+
|
|
26
|
+
## Local service
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
systemctl --user is-enabled promptlatch.service
|
|
30
|
+
systemctl --user is-active promptlatch.service
|
|
31
|
+
curl --retry 10 --retry-connrefused --retry-delay 1 -fsS http://127.0.0.1:8000/healthz
|
|
32
|
+
curl --retry 10 --retry-connrefused --retry-delay 1 -fsS http://127.0.0.1:8000/openapi.json | jq -r .info.version
|
|
33
|
+
docker exec promptlatch-local promptlatch version
|
|
34
|
+
curl --retry 10 --retry-connrefused --retry-delay 1 -fsS http://127.0.0.1:8787/healthz
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Both health endpoints must report redaction enabled, `detect-secrets`, and `telemetry:false`.
|
|
38
|
+
Both runtimes must report release version. `promptlatch-local` must bind loopback, restart unless
|
|
39
|
+
stopped, and run with raw-request debug off.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Testing
|
|
2
|
+
|
|
3
|
+
Run from repository root. Never use real credentials in tests or logs.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
uv sync --extra dev --group audit --locked
|
|
7
|
+
uv run scripts/check_release.py
|
|
8
|
+
uv run scripts/audit_secrets.py
|
|
9
|
+
uv run ruff check .
|
|
10
|
+
uv run ruff format --check .
|
|
11
|
+
uv run pyright src tests scripts
|
|
12
|
+
uv run pytest
|
|
13
|
+
uv run pip-audit
|
|
14
|
+
uv build
|
|
15
|
+
helm lint ./charts/promptlatch
|
|
16
|
+
helm template promptlatch ./charts/promptlatch >/dev/null
|
|
17
|
+
uv run scripts/check_helm.py
|
|
18
|
+
docker build -t promptlatch:release-check .
|
|
19
|
+
docker run --rm --entrypoint promptlatch promptlatch:release-check version
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Before release, also run checks under Python 3.12, 3.13, and 3.14:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
UV_PROJECT_ENVIRONMENT=/tmp/promptlatch-py312 uv sync --python 3.12 --extra dev --locked
|
|
26
|
+
UV_PROJECT_ENVIRONMENT=/tmp/promptlatch-py312 uv run pytest
|
|
27
|
+
UV_PROJECT_ENVIRONMENT=/tmp/promptlatch-py313 uv sync --python 3.13 --extra dev --locked
|
|
28
|
+
UV_PROJECT_ENVIRONMENT=/tmp/promptlatch-py313 uv run pytest
|
|
29
|
+
UV_PROJECT_ENVIRONMENT=/tmp/promptlatch-py314 uv sync --python 3.14 --extra dev --locked
|
|
30
|
+
UV_PROJECT_ENVIRONMENT=/tmp/promptlatch-py314 uv run pytest
|
|
31
|
+
```
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Changes to redaction, forwarding, config, logs, or tracing need an explicit privacy review.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
uv sync --extra dev --group audit --locked
|
|
9
|
+
uv run promptlatch doctor
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Checks
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
uv run scripts/audit_secrets.py
|
|
16
|
+
uv run ruff check .
|
|
17
|
+
uv run pytest
|
|
18
|
+
uv build
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Release
|
|
22
|
+
|
|
23
|
+
Release tags create GitHub releases through `.github/workflows/release.yml`.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
VERSION=0.2.1
|
|
27
|
+
uv run scripts/check_release.py --tag "v${VERSION}"
|
|
28
|
+
uv run scripts/audit_secrets.py
|
|
29
|
+
uv run ruff check .
|
|
30
|
+
uv run pytest
|
|
31
|
+
uv build
|
|
32
|
+
git tag -s "v${VERSION}" -m "PromptLatch ${VERSION}"
|
|
33
|
+
git push origin main "v${VERSION}"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Before tagging, keep these versions identical:
|
|
37
|
+
|
|
38
|
+
- `pyproject.toml`
|
|
39
|
+
- `src/promptlatch/version.py`
|
|
40
|
+
- `charts/promptlatch/Chart.yaml`
|
|
41
|
+
- `charts/promptlatch/values.yaml`
|
|
42
|
+
- `uv.lock`
|
|
43
|
+
|
|
44
|
+
Release workflow reruns checks, builds source, wheel, and Helm artifacts, writes
|
|
45
|
+
`SHA256SUMS`, attests build provenance, publishes SBOM-backed container image, and
|
|
46
|
+
uploads release assets.
|
|
47
|
+
|
|
48
|
+
If publishing fails after release creation, fix workflow on `main` and rerun
|
|
49
|
+
existing immutable tag:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
gh workflow run release.yml --ref main -f tag="v${VERSION}"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Secret hygiene
|
|
56
|
+
|
|
57
|
+
- Do not put real secrets, customer prompts, credentials, or private config in issues, tests, docs, commits, or screenshots.
|
|
58
|
+
- Use split fixture strings like `"sk-" + "FixtureToken..."` when tests need provider-shaped values.
|
|
59
|
+
- Prefer full masking in examples: `[REDACTED_SECRET]`.
|
|
60
|
+
- Run secret audit before opening a pull request.
|
|
61
|
+
|
|
62
|
+
## Redaction rules
|
|
63
|
+
|
|
64
|
+
- Keep detection local and deterministic. Do not add model calls.
|
|
65
|
+
- Do not enable entropy-only detectors without tightly bounded false positives.
|
|
66
|
+
- Tests for new provider patterns must prove full redaction and comma-separated redaction.
|
|
67
|
+
|
|
68
|
+
## Emergency request tracing
|
|
69
|
+
|
|
70
|
+
`promptlatch serve --debug-requests` logs raw request bodies. Use only with local fixture values.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim@sha256:e5b65587bce7de595f299855d7385fe7fca39b8a74baa261ba1b7147afa78e58 AS builder
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY pyproject.toml uv.lock README.md ./
|
|
5
|
+
COPY src ./src
|
|
6
|
+
RUN uv sync --no-dev --no-editable --locked
|
|
7
|
+
|
|
8
|
+
FROM python:3.12-slim@sha256:229a2c5bfa27522db7815ea81f9bed70af17ccb9de9fc7ad142b1877b5830d36
|
|
9
|
+
|
|
10
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
11
|
+
PROMPTLATCH_HOST=0.0.0.0 \
|
|
12
|
+
PROMPTLATCH_PORT=8000
|
|
13
|
+
|
|
14
|
+
WORKDIR /app
|
|
15
|
+
RUN groupadd --gid 10001 promptlatch \
|
|
16
|
+
&& useradd --uid 10001 --gid 10001 --create-home --shell /usr/sbin/nologin promptlatch
|
|
17
|
+
COPY --from=builder --chown=promptlatch:promptlatch /app /app
|
|
18
|
+
USER 10001:10001
|
|
19
|
+
EXPOSE 8000
|
|
20
|
+
CMD ["promptlatch", "serve", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PromptLatch contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|