DBS — Django Backup Solution
🚧 Under development. DBS is in active development and its API may change.
Created by Sudum Technology — Research and Development sector. Our very tiny contribution to this world.
DBS backs up a Django project into one encrypted file — rows, relations and files together. That file is redundant and self-healing: it holds two copies of your data plus Reed-Solomon parity, so silent corruption is detected and repaired when you restore, instead of quietly poisoning the data you were relying on.
You drive it three ways: a command (manage.py dbs), a control panel in the
Django admin, and a dbs-client command that pulls backups onto your own
machine.
Quick start
1. Install and enable it.
pip install django-dbs
# settings.py
INSTALLED_APPS = [
...,
"django.contrib.admin",
"dbs",
]
MIDDLEWARE = [
...,
"dbs.security.middleware.DBSSecurityMiddleware",
]
python manage.py migrate
2. Take a backup.
python manage.py dbs backup backup.dbs
That's it. No passphrase to invent — DBS derives one from your SECRET_KEY.
3. Check it.
python manage.py dbs validate backup.dbs --passphrase
4. Rehearse a restore (changes nothing):
python manage.py dbs restore backup.dbs --dry-run
Then open /admin/dbs/ as a superuser for the control panel.
One thing to write down. Your backups are encrypted with a key derived from
SECRET_KEY. If you ever changeSECRET_KEYwithout keeping the old value inSECRET_KEY_FALLBACKS, older backups can no longer be opened. Runpython manage.py dbs key --showand store the result somewhere safe.
What you get
- One encrypted file per backup — rows, relations and files.
- Two copies plus Reed-Solomon parity inside it, so bit-rot is repaired on restore rather than inherited.
- Nothing to configure: the encryption key comes from
SECRET_KEY. - A control panel at
/admin/dbs/, mounted automatically, in the admin's own theme. - A session guard on that panel: superusers only, every request scored, and a shell command that always lets you back in.
- Scheduled backups with retention, and off-site copies over SFTP.
dbs-clientto pull backups onto your laptop over SSH.- Instructions for AI coding assistants, shipped inside the package.
The control panel
Once dbs is installed alongside django.contrib.admin and you have run
migrate, the panel is at /admin/dbs/. There is no urls.py change to
make.
| Page | What it does |
|---|---|
| Dashboard | Recent backups, your SFTP targets, current guard state |
| Take a backup | Download it, or push it straight to a target |
| Restore | Upload a .dbs file — with a dry run that changes nothing |
| SFTP targets | Add and edit servers; credentials are encrypted at rest |
| Console | Per target: check the connection, list backups, run one on the server |
| Wiki | Passphrases, restore semantics, the guard, troubleshooting |
Superusers only. There is deliberately no grantable permission for it: the panel can download and overwrite your entire database.
On your first visit a short wizard asks which networks you log in from and how strict the guard should be. You can change all of it later from the panel.
The older include("dbs.contrib.urls") pages still work unchanged.
Backups on a schedule
python manage.py dbs schedule --interval 6h --output-dir /var/backups/myproject --keep 14
| Flag | Meaning |
|---|---|
--interval |
How often: 90s, 30m, 6h, 1d. Default DBS_SCHEDULE_INTERVAL, else 24h |
--output-dir |
Where backups land. Default DBS_BACKUP_DIR |
--prefix |
Filename prefix, so several projects can share a directory |
--keep |
How many local backups to retain |
--push |
Name of a DBS_SSH_TARGETS entry to upload to as well |
--keep-remote |
How many uploaded backups to retain |
--once |
Run one cycle and exit — use this from cron, or to test |
Backups are named prefix-YYYYMMDD-HHMMSSZ.dbs in UTC, so sorting by name
sorts by time. Retention only ever considers files matching that pattern and
prefix; anything else in the directory is left alone.
Run one scheduler per output directory — two loops sharing a directory race on retention. A failing cycle is logged and the schedule carries on.
Running it under systemd
[Unit]
Description=DBS scheduled backups
After=network-online.target
[Service]
User=deploy
WorkingDirectory=/srv/myproject
ExecStart=/srv/myproject/.venv/bin/python manage.py dbs schedule --interval 6h \
--output-dir /var/backups/myproject --keep 14
Restart=always
[Install]
WantedBy=multi-user.target
SIGTERM stops the loop immediately rather than after the current interval, so
systemctl restart and container shutdowns are prompt.
For cron, use --once for a single cycle. In Docker, run the loop as the
container's main process.
Off-site copies over SFTP
Two ways to define a server. In settings, for automation:
# settings.py — reference a key by path; no secrets in the file
DBS_SSH_TARGETS = {
"offsite": {
"host": "backups.example.com",
"username": "deploy",
"key_filename": "/home/deploy/.ssh/id_ed25519",
"known_hosts": "/home/deploy/.ssh/known_hosts",
"remote_dir": "/var/backups/myproject",
}
}
Or in the admin, under SFTP targets, where passwords and private keys are
encrypted at rest under a key derived from SECRET_KEY and never shown again
once saved.
Then push on every scheduled cycle:
python manage.py dbs schedule --interval 6h --output-dir /var/backups \
--push offsite --keep-remote 7
Host keys are verified and unknown hosts are rejected by default. Point
known_hosts at a file, or set auto_add_host_key to trust whatever key the
server presents on first contact — which gives up detection of a
machine-in-the-middle on that first connection.
Needs pip install "django-dbs[ssh]".
Restoring
python manage.py dbs restore backup.dbs --dry-run # rehearse, change nothing
python manage.py dbs restore backup.dbs # merge into what's there
python manage.py dbs restore backup.dbs --flush # replace instead of merge
Start with --dry-run. It performs the real load inside a transaction it
rolls back, and writes no files, so you see exactly what would happen.
Things worth knowing before you restore for real:
- It merges by default. Rows created after the backup was taken are not
deleted.
--flushclears the backed-up models first — children before parents, in the same transaction — so the restore replaces instead. - The load is one transaction. If anything fails midway the database is left untouched.
- File writes are confined to directories listed in
DBS_RESTORE_ROOTS(orDBS_FILE_ROOTSif that is unset). Anything outside raisesRestoreError. Set this before restoring backups that embed external files. - Migration drift is reported. A backup records the applied migration per app; restoring onto a target that has moved on warns and names the apps. Fields and models the target does not know are discarded as rows load.
- Sequences are reset after rows carrying explicit primary keys, so the next row your project creates does not collide with a restored one.
Signals during a restore
Rows are saved the way loaddata does, with raw=True. A post_save receiver
that re-runs business side effects must return early on raw saves, or a restore
replays them against a half-loaded database:
@receiver(post_save, sender=Order)
def on_order_saved(sender, instance, created, **kwargs):
if kwargs.get("raw"):
return
...
Pulling backups to your own machine
dbs-client connects to a server running DBS, asks it for a fresh backup, and
downloads the file — over one encrypted SSH connection.
pip install "django-dbs[client]"
dbs-client init # writes dbs-client.toml, mode 600
$EDITOR dbs-client.toml
dbs-client test-connection
dbs-client backup
[defaults]
server = "production"
dest = "~/dbs-backups"
keep = 14
[servers.production]
host = "app.example.com"
username = "deploy"
key_filename = "~/.ssh/production.pem"
known_hosts = "~/.ssh/known_hosts"
project_dir = "/srv/myproject"
python = "/srv/myproject/.venv/bin/python"
django_settings_module = "myproject.settings.production"
remote_dir = "/var/backups/myproject"
passphrase_env = "DBS_PASSPHRASE"
| Command | What it does |
|---|---|
init |
Write a starter config (mode 600, never overwrites). --print to stdout |
test-connection |
Check auth, host key policy, remote directory, server version |
list |
List remote backups with size and time |
backup |
Make a backup on the server and download it |
pull NAME / pull --latest |
Download a backup that already exists |
push PATH |
Upload a local backup file to the server |
prune |
Apply retention locally, remotely, or both. --dry-run first |
schedule |
Repeat backup on an interval. --once for one cycle |
validate PATH |
Check a local backup file — no Django project needed |
Downloads stream to a .part file and are renamed only once complete, so an
interrupted transfer can never be mistaken for a good backup.
dbs-client never restores into a server's database. Use push to place a file
there, then run the restore on the server deliberately.
Config keys and SSH authentication
Anything under [defaults] applies to every server unless that server overrides
it. Pick a server with --server NAME.
| Key | Meaning |
|---|---|
host · username · port |
Where to connect. host and username required |
key_filename |
.pem or OpenSSH private key. ~ is expanded |
key_passphrase · key_passphrase_env |
For an encrypted key file |
password · password_env |
Password authentication |
use_agent |
Use ssh-agent (default true) |
known_hosts · auto_add_host_key |
Host key verification |
connect_timeout |
Seconds to wait for the SSH handshake |
remote_dir |
Where backups live on the server. Created if missing |
project_dir · python · manage · django_settings_module |
How to run manage.py remotely |
env |
Extra environment variables for the remote command |
passphrase · passphrase_env |
The backup encryption passphrase |
passphrase_transport |
stdin (default) or env |
database |
Database alias to back up |
dest · prefix · keep · keep_remote · interval |
Local defaults |
exec_timeout |
Seconds to allow the remote backup to run |
Any secret can be read from an environment variable instead of the file by
adding _env to the key name.
An unrecognised key is an error, not a warning — a typo like known_host would
otherwise silently disable host key checking. A config holding a literal secret
and readable by other users is refused, as is one writable by other users.
The passphrase never appears in a command line, locally or on the server,
because process arguments are readable by every user via /proc. By default the
client runs the remote backup with --passphrase-stdin and writes the
passphrase down the SSH channel, so it is in neither the remote process's
arguments nor its environment.
The client invokes manage.py dbs_backup on the server, which is the original
command name and still fully supported.
Choosing what to back up
By default DBS finds every model, treats FileField/ImageField as files, and
preserves relations. Register a model only to override that, in a dbs.py inside
your app (auto-discovered like admin.py):
# myapp/dbs.py
from dbs import backup_registry, FieldType, ModelBackup
from .models import Invoice
@backup_registry.register(Invoice)
class InvoiceBackup(ModelBackup):
overrides = {
"scanned_pdf_path": FieldType.FILE_PATH, # a path column -> embed the file
"render_cache": FieldType.EXCLUDE, # skip this column
}
file_roots = ["/srv/myapp/uploads"] # extra file trees
FieldType values: VALUE (default), FILE, FILE_PATH, EXCLUDE.
DBS_EXCLUDE_MODELS skips models in addition to the built-in exclusions
(content types, permissions, admin log, sessions, and DBS's own tables). Prefix
a label with - to back up one the defaults skip:
DBS_EXCLUDE_MODELS = ["myapp.AuditRow", "-sessions.Session"]
Passphrases
DBS derives the backup passphrase from SECRET_KEY, so a new project needs no
setup. The derivation is domain separated, meaning the backup key is never the
same bytes Django uses for sessions, CSRF and password-reset tokens.
Order of precedence:
--passphraseor--passphrase-stdinon the command line- The
DBS_PASSPHRASEenvironment variable - The
DBS_PASSPHRASEsetting - Derived from
SECRET_KEY
python manage.py dbs key --show # print it, and archive it somewhere safe
Rotating SECRET_KEY: keep the old value in SECRET_KEY_FALLBACKS. DBS
tries every fallback when restoring and when reading stored SFTP credentials. A
backup encrypted under a key you lost, and did not keep as a fallback, cannot be
opened by anyone.
To keep the passphrase out of the process's command line:
printf '%s\n' "$SECRET" | python manage.py dbs backup backup.dbs --passphrase-stdin
The session guard
The panel can export and overwrite your whole database, so every admin request from a superuser is scored, and a high enough score ends that account's sessions.
What feeds the score: time of day, request rate, how risky the attempted action
is, session age, recent failed logins, and whether the network prefix and
browser are ones the account has used before. Scoring uses an
IsolationForest — shipped pre-trained on a synthetic corpus so it works from
the first request, then refitted on the account's own history once there is
enough of it.
If it locks you out, a shell always wins:
python manage.py dbs security unlock alice
Other subcommands: status, policy, retrain, reset-baseline USER,
events, purge.
Ways to loosen it:
DBS_TRUSTED_NETWORKS |
CIDRs that are scored and recorded but never enforced against |
DBS_ANOMALY_ENFORCE = False |
Turn enforcement off entirely |
| Setup wizard | Pick Relaxed instead of Balanced, Strict or Paranoid |
| Learning period | New installs record without enforcing for the first sessions |
Optional browser location. DBS_GEOLOCATION = True adds distance from a
known location and impossible-travel detection. It is opt-in, stored rounded to
about a kilometre, and can only ever raise a risk score, never lower one —
it comes from the browser and can be forged. Declining the permission prompt
changes nothing else.
Remote command execution is off by default. DBS_ADMIN_CONSOLE_SHELL = True
adds a free-form command box to the target console, which gives any superuser
arbitrary command execution on that server from a browser. The named actions —
check connection, list backups, create the remote directory — always work
without it.
Working with AI assistants
DBS ships instructions that teach a coding assistant how to use it correctly: the settings, the commands, the restore semantics, and the mistakes that lose data.
python manage.py dbs ai # writes .claude/skills/django-dbs/
python manage.py dbs ai --agents # also appends a section to AGENTS.md
python manage.py dbs ai --check # CI: fail if the installed copy has drifted
The source of truth lives inside the installed package under dbs/ai/, so it
always matches the version you actually have.
Command reference
python manage.py dbs # overview of everything below
python manage.py dbs backup OUTPUT
python manage.py dbs restore INPUT [--dry-run] [--flush] [--no-data] [--no-files]
python manage.py dbs validate INPUT [--passphrase]
python manage.py dbs schedule [--interval 6h] [--output-dir DIR] [--once]
python manage.py dbs key [--show]
python manage.py dbs security ACTION [USERNAME]
python manage.py dbs ai [--agents] [--check] [--print]
python manage.py dbs upgrade [--check] [--self] [--backups DIR] [--offline]
Every command takes --passphrase, --passphrase-stdin and --database where
they make sense. backup also takes --no-compress, --no-verify,
--block-size, --kdf-time and --kdf-memory.
python manage.py django-dbs runs the same command under its older name. The
original dbs_backup, dbs_restore, dbs_validate and dbs_schedule commands
still work exactly as before and are not deprecated.
Settings reference
Everything is optional. DBS works with none of these set.
What to back up
| Setting | Purpose |
|---|---|
DBS_EXCLUDE_MODELS |
Models to skip, in addition to the defaults. -label re-includes one |
DBS_FILE_ROOTS |
Extra directories embedded in every backup |
DBS_RESTORE_ROOTS |
Directories a restore may write into (falls back to DBS_FILE_ROOTS) |
Where backups go
| Setting | Purpose |
|---|---|
DBS_BACKUP_DIR |
Default output directory for dbs schedule |
DBS_BACKUP_PREFIX |
Default filename prefix |
DBS_SCHEDULE_INTERVAL |
Default interval (default 24h) |
DBS_SCHEDULE_KEEP |
Default local retention count (default 7) |
DBS_SSH_TARGETS |
Named SFTP connection profiles |
DBS_SCHEDULE_PUSH_TARGET |
Default target to push to |
DBS_SCHEDULE_KEEP_REMOTE |
Default retention for pushed backups |
Encryption
| Setting | Purpose |
|---|---|
DBS_PASSPHRASE |
Explicit passphrase, overriding the one derived from SECRET_KEY |
DBS_KDF_TIME_COST · DBS_KDF_MEMORY_COST · DBS_KDF_PARALLELISM |
Argon2id cost for new backups |
The panel and its guard
| Setting | Purpose |
|---|---|
DBS_SETUP_WIZARD |
Redirect superusers to the wizard until configured. Default True |
DBS_ADMIN_CONSOLE_SHELL |
Allow free-form SSH commands from the console. Default False |
DBS_ANOMALY_ENFORCE |
Whether a blocking verdict ends sessions. Default True |
DBS_TRUSTED_NETWORKS |
CIDRs scored but never enforced against |
DBS_ANOMALY_DETECTOR |
Dotted path to a replacement detector class |
DBS_ANOMALY_MIN_ROWS |
Events before a per-account model is fitted (default 50) |
DBS_GUARD_POLL_SECONDS |
How often an open page re-checks authorization (default 15) |
DBS_GUARD_EVERYWHERE |
Extend the guard poller to the whole admin. Default False |
DBS_GEOLOCATION |
Collect browser location as a signal. Default False |
DBS_SECURITY_RETENTION_DAYS |
Telemetry retention for dbs security purge (default 90) |
DBS_MAX_UPLOAD_BYTES |
Restore upload cap (default 1 GiB) |
DBS_MAX_PAYLOAD_BYTES |
Decompressed payload cap on restore (default 4 GiB) |
DBS_TRUST_FORWARDED_FOR |
Read the client IP from X-Forwarded-For. Default False |
DBS_TRUSTED_PROXIES |
Proxies in front, counted from the right of that header (default 1) |
Only enable DBS_TRUST_FORWARDED_FOR behind a proxy you control, and set
DBS_TRUSTED_PROXIES to the number of hops — otherwise the client address is
whatever the caller claims.
Python API
from dbs import create_backup, restore_backup, validate_backup
blob = create_backup("passphrase", output="backup.dbs")
report = validate_backup(blob, "passphrase") # report.ok, report.summary()
result = restore_backup(blob, "passphrase") # result.healed if it repaired corruption
from dbs import default_passphrase # the one derived from SECRET_KEY
from dbs.transports import SSHTarget, open_session
with open_session(SSHTarget.from_settings("offsite")) as session:
session.push("backup.dbs", "backup.dbs")
for item in session.details():
print(item.name, item.size, item.modified)
open_session reuses one connection for a whole cycle. The module-level
push_backup, pull_backup, pull_backup_to, list_backups,
list_backup_details, delete_backup and check_connection helpers open and
close a connection each.
How it heals
On write, the encrypted stream is split into blocks. Each block gets a BLAKE2b hash and a layer of Reed-Solomon parity, and the whole stream is stored twice — header and manifest included. On read, each block is taken from whichever copy verifies, and sparse bit-flips are corrected in place even when both copies are hit. Every recovered block is checked against its stored hash, so a mis-correction cannot slip through. A freshly written backup is re-read and verified end-to-end before the command reports success.
Recoverable: whole-block loss in one copy, and sparse byte errors in both copies up to the parity budget (~8 bytes per 255-byte codeword by default).
Not recoverable: a block destroyed beyond the parity budget in both copies. DBS then refuses to restore and names the failed blocks, rather than handing you silently wrong data.
Security model
- Argon2id derives a key from the passphrase. Raise
KDFParamscost for more resistance. - Envelope encryption: a random data key encrypts the payload with AES-256-GCM, and that data key is wrapped by the passphrase-derived key. The file stores the salt, the Argon2 parameters and the wrapped key — never the passphrase, never the raw data key.
- A wrong passphrase fails the GCM tag check and is reported as such. It can never produce partial or garbage data.
- Stored SFTP credentials are encrypted at rest with AES-256-GCM under a
separately derived
SECRET_KEYkey, and are never displayed again. - Transfers run over SSH/SFTP with host key verification on by default.
See SECURITY.md for the reporting process and the threat model.
Observability
DBS logs to the dbs logger: backup and restore start and finish, skipped
files, SFTP transfers, scheduled cycles and retention, and — most importantly —
a WARNING whenever silent corruption was detected and healed. Route that
logger somewhere you will see it, so a degrading disk is noticed before both
copies are damaged.
LOGGING = {
"version": 1,
"loggers": {"dbs": {"handlers": ["console"], "level": "INFO"}},
}
dbs-client --verbose prints the same log to stderr.
Troubleshooting
"Credential cannot be read with the current SECRET_KEY"
The stored SFTP credential was encrypted under a different key. Add the old key
to SECRET_KEY_FALLBACKS, or re-enter the credential in the admin.
The panel logged me out
The guard scored the request above your logout threshold. Run
python manage.py dbs security unlock USERNAME, then add your network to the
trusted list in the setup wizard.
A restore merged when I wanted it to replace
Use --flush, or tick Replace instead of merge in the panel.
The scheduler will not start
It needs somewhere to write: pass --output-dir or set DBS_BACKUP_DIR.
/admin/dbs/ gives a 404
The panel is superusers only, and needs django.contrib.admin in
INSTALLED_APPS alongside dbs.
A restore raises RestoreError about a path
File restores are confined to DBS_RESTORE_ROOTS (or DBS_FILE_ROOTS). Add the
directory the backup wants to write into.
Upgrading
One command tells you what this project still needs, and does the parts that are safe to do automatically:
python manage.py dbs upgrade
DBS 0.3.1
[ok] installed app dbs is in INSTALLED_APPS
[done] migrations applied the pending dbs migrations
[ok] dependencies scikit-learn is available
[warn] session guard the control panel is reachable but nothing is scoring requests
MIDDLEWARE = [..., "dbs.security.middleware.DBSSecurityMiddleware"]
It applies pending DBS migrations and refreshes the shipped AI instructions itself. Anything that means editing your own code it prints, with the exact line and where it goes — it never rewrites your settings.
--check |
Report only, change nothing. Exits non-zero if something needs doing — use this in CI |
--self |
Install a newer django-dbs from PyPI if one exists. Refuses on a source checkout |
--backups DIR |
Also read the backups in DIR and convert any written in an older format |
--offline |
Do not contact PyPI |
python manage.py dbs-upgrade and python manage.py dbs_upgrade are the same command.
What it checks
Installed app, pending migrations, scikit-learn, whether the panel is mounted, whether the
guard middleware is active, DBS_EXCLUDE_MODELS written for pre-0.2.2 semantics, whether a
passphrase can be derived, whether DBS_RESTORE_ROOTS would refuse every path, and whether
the installed AI instructions match the version you have.
Old backups
python manage.py dbs upgrade --backups /var/backups/myproject
Every backup ever written by any released DBS is at container format version 1, which this version reads, so today this reports "nothing to convert". It exists because a future format change would otherwise strand files that already exist.
When a backup can't be read forward, the command stops and changes nothing:
- It never deletes, moves or overwrites a backup — not with a flag, not with confirmation.
Conversion writes a new
.convertedfile beside the original and leaves the original alone. - A converted file is validated end to end before it counts as converted.
- It tells you the safe option first: install the version that wrote the file in a separate environment and restore from there. You rarely need to give anything up.
Only if you genuinely no longer need those files can you continue, and doing so is deliberately hard to automate: there is no flag, it requires a terminal, and it requires typing an exact phrase naming how many backups you are giving up. Even then nothing is deleted — the files stay on disk.
From 0.2.x
pip install --upgrade django-dbspython manage.py dbs upgrade
That applies the migrations 0.3.0 added and tells you about anything else. scikit-learn
arrives automatically as a dependency. Your existing backups restore unchanged, and the
dbs_backup / dbs_restore / dbs_validate / dbs_schedule commands keep working.
Development
pip install -e ".[dev]"
pytest
Set DBS_TEST_HOUR=3 to run the suite as though it were 03:00 UTC — the session
guard scores time of day, so this makes that behaviour reproducible.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_dbs-0.3.1.tar.gz.
File metadata
- Download URL: django_dbs-0.3.1.tar.gz
- Upload date:
- Size: 199.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4706322b0db22566cd65e7f5825ccb935f2574b05075c00b2b90a7d9ad96697f
|
|
| MD5 |
0d6654f9270d7bfd8cb6b6f6f16f233d
|
|
| BLAKE2b-256 |
77d010a0317604a9f40eb5e9ffe2089bbcfcc9da82ff3cce408969410437e3a0
|
Provenance
The following attestation bundles were made for django_dbs-0.3.1.tar.gz:
Publisher:
publish.yml on bn7ya/dbs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_dbs-0.3.1.tar.gz -
Subject digest:
4706322b0db22566cd65e7f5825ccb935f2574b05075c00b2b90a7d9ad96697f - Sigstore transparency entry: 2724657820
- Sigstore integration time:
-
Permalink:
bn7ya/dbs@0b24e1735049803e878e54c286807544cdc00e10 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/bn7ya
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0b24e1735049803e878e54c286807544cdc00e10 -
Trigger Event:
release
-
Statement type:
File details
Details for the file django_dbs-0.3.1-py3-none-any.whl.
File metadata
- Download URL: django_dbs-0.3.1-py3-none-any.whl
- Upload date:
- Size: 181.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8eb7e47789d2d3f14fb97c9a6bdd70b67d4906abc633c46c3e6475bddf4e3a30
|
|
| MD5 |
9d01ffe7cee7777f6ee6db17e1958658
|
|
| BLAKE2b-256 |
a645874149eadbc2f27fb9ec277e8eccff66e2b3e3bb93ab15c519de0a0663f8
|
Provenance
The following attestation bundles were made for django_dbs-0.3.1-py3-none-any.whl:
Publisher:
publish.yml on bn7ya/dbs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_dbs-0.3.1-py3-none-any.whl -
Subject digest:
8eb7e47789d2d3f14fb97c9a6bdd70b67d4906abc633c46c3e6475bddf4e3a30 - Sigstore transparency entry: 2724658175
- Sigstore integration time:
-
Permalink:
bn7ya/dbs@0b24e1735049803e878e54c286807544cdc00e10 -
Branch / Tag:
refs/tags/v0.3.1 - Owner: https://github.com/bn7ya
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0b24e1735049803e878e54c286807544cdc00e10 -
Trigger Event:
release
-
Statement type: