atrib client SDK: verifiable agent actions. attest/recall verbs, Ed25519-signed chain-linked records, byte-identical to the TypeScript implementation.
Project description
atrib (Python SDK)
Python client SDK for atrib: verifiable agent actions. Every action becomes signed context for the next.
This is the first non-TypeScript implementation of the atrib record layer
(spec §1) and SDK contract (spec §5). The guarantee that matters:
byte-identity. Identical inputs produce identical JCS canonical forms
(RFC 8785), Ed25519 signatures over the same bytes, identical record
hashes, propagation tokens, and chain roots as the TypeScript
implementation, verified against the shared conformance corpora in
spec/conformance/ (1.4 signing + adversarial, 1.2.6 provenance_token,
1.2.3 multi-producer chain composition, 2.6.1 submission validation) and a
cross-implementation determinism harness.
Install
pip install atrib # once published; unpublished today, install from source:
pip install -e python/
Dependencies: cryptography (Ed25519), rfc8785 (JCS), typing_extensions.
Usage
from atrib import AtribClient, AttestRef
client = AtribClient() # key from ATRIB_PRIVATE_KEY / ATRIB_KEY_FILE
result = client.attest(
{"what": "chose sqlite over postgres", "why_noted": "deployment constraint"},
)
client.attest(
{"summary": "supersedes the sqlite decision", "reason": "scale changed"},
ref=AttestRef(kind="revises", record_hash=result.record_hash),
)
history = client.recall(shape="history", limit=10)
client.flush()
The record layer is directly importable for hosts that own their pipeline:
from atrib import (
build_and_sign_emit_record, sign_record, verify_record,
resolve_chain_root, genesis_chain_root, record_hash_ref,
encode_token, decode_token, derive_provenance_token,
)
API reference
Everything below is importable from the package root (from atrib import …).
The client layer (AtribClient and its result dataclasses) sits on top of a
fully exposed record layer; hosts can use either level.
AtribClient
AtribClient(
*,
key=..., # ResolvedKey | None | unset
context_id=None, # str | None (32 lowercase hex)
anchors=None, # list[AnchorSpec] | None
allow_single_anchor=False, # §2.11.12 rule 3 opt-in
producer="atrib-sdk-py", # _local.producer sidecar label (DEFAULT_PRODUCER)
mirror_write_path=None, # Path | str | None
mirror_read_path=None, # Path | str | None
env=None, # Mapping[str, str] | None (default os.environ)
)
Constructor parameters (all keyword-only):
| Parameter | Default | Meaning |
|---|---|---|
key |
unset → lazy resolve_key(env) ladder |
Pre-resolved ResolvedKey. Passing the parameter at all (including None) skips the ladder; None disables signing (pass-through per §5.8 rule 5). |
context_id |
None → env discovery |
Per-client default context. Env discovery is the D078/D083 subset: ATRIB_CONTEXT_ID, then CLAUDE_CODE_SESSION_ID / CODEX_THREAD_ID (UUID stripped of hyphens + lowercased to 32-hex). |
anchors |
None → BUILT_IN_DEFAULT_ANCHOR_SET (two anchors; the atrib-log member honors $ATRIB_LOG_ENDPOINT) |
D138 anchor set (AnchorSpec = str | Mapping: bare §2.6.1 endpoint shorthand for {"url": ...}, or an AnchorDescriptor mapping; url wins over endpoint). Skip rules mirror the TS resolveAnchorSet exactly: hostile shapes and anchor_type values outside the §2.11.8 registry warn-and-skip (never raise) and are excluded from the plurality posture. Attests fan out to every usable atrib-log anchor through one non-blocking §2.6.1 queue per endpoint; registered non-atrib-log types (sigstore-rekor, rfc3161-tsa, opentimestamps) count toward plurality but their legs are skipped with a warning: no Python transport yet (the TS reference stubs them too). |
allow_single_anchor |
False |
§2.11.12 rule 3: states a < 2-anchor set is deliberate, silencing the sub-plurality warning and the _local.anchor_config sidecar degradation marker. |
producer |
"atrib-sdk-py" |
_local.producer mirror-sidecar label (§5.9). |
mirror_write_path |
default_mirror_write_path(env) |
Where new records are appended. |
mirror_read_path |
default_mirror_read_path(env) |
Shared chain-inheritance read source. |
env |
os.environ |
Injectable environment mapping (for tests and embedded hosts). |
The client is a context manager: __exit__ flushes the submission queue
with a 5-second deadline and never raises.
attest(content, *, ...) -> AttestResult
client.attest(
content, # Mapping[str, object]: required, positional
event_type=None, # short name or absolute URI; default 'observation'
ref=None, # AttestRef(kind='annotates'|'revises', record_hash=...)
informed_by=None, # list[str] of sha256:<64-hex> refs
context_id=None, # overrides the client default
chain_root=None, # explicit override (requires a context_id)
provenance_token=None, # §1.2.6 genesis-only anchor (see below)
tool_name=None,
args_hash=None, # overrides the D099 default sha256(JCS(content))
result_hash=None,
timestamp_ms=None, # clock injection for deterministic tests
)
Single write verb; signs in-process via the ported record layer and mirrors
- submits per §5.9/§5.3.5.
The only raise paths are contradictory inputs (
ValueError): an invalidevent_typeURI, aref.kindthat contradicts an explicitevent_type, an unknownref.kind, anannotates/revisesref that is notsha256:<64-hex>, an annotation/revisionevent_typewithout the matchingref, an explicitchain_rootwith no resolvablecontext_id, acontext_idthat is not 32 lowercase hex, or aprovenance_tokenon a context that already has records on the local mirror (the §1.2.6 genesis-only invariant). Everything operational degrades:
- No signing key → pass-through result (
via="none",record_hash=None) with a warning. - No context_id anywhere → a fresh orphan context is synthesized (§1.5.1; never inherited from the mirror tail) with a warning.
- Signing, mirror-write, or submission-enqueue failures append warnings and never raise.
The default chain_root comes from resolve_chain_root with the mirror
tail (write mirror preferred, then the read source, the @atrib/emit
inheritance ordering). The mirror sidecar carries
{"producer": ..., "content": ...}; the signed record commits to content
through the default args_hash per
D099.
AttestRef is a frozen dataclass: AttestRef(kind, record_hash) with
kind one of 'annotates' / 'revises' (deriving event types
annotation / revision).
AttestResult (frozen dataclass): record_hash (sha256:<64-hex> or
None), context_id, via ('in-process' | 'none'), warnings
(atrib:-prefixed strings), and anchor_posture, the resolved
§2.11.12
posture dict {"effective_anchor_count", "used_default_set", "warned"}
(present even in pass-through mode). When a sub-plurality set lacks
allow_single_anchor, the mirror sidecar additionally carries the
_local.anchor_config degradation marker
{"configured": <n>, "allow_single_anchor": false}.
recall(*, shape="history", ...) -> RecallOutcome
client.recall(
shape="history", # 'history' | 'session_chain' in v0
context_id=None, # session_chain defaults from the client
event_type=None, # short name or URI (normalized)
creator_key=None,
limit=10,
since_ms=None,
until_ms=None,
verify_signatures=True,
)
Single read verb over the local mirror (read source + write mirror, newest
first). v0 serves the history and session_chain shapes; any other shape
degrades to via="none" with a warning pointing at the TypeScript SDK or
the primitives runtime, and never raises. With verify_signatures=True
(default), records failing
§1.4.3
verification are dropped and each returned entry carries
signature_verified. Entries carry record_hash, event_type,
context_id, creator_key, timestamp, and local_content when the
mirror sidecar kept the content.
RecallOutcome (frozen dataclass): shape, via
('in-process' | 'none'), data ({"total", "returned", "records"} or
None), warnings.
flush(deadline_s=30.0) -> None
Bounded wait for pending log submissions on every anchor leg (one queue per effective atrib-log anchor). Never raises.
Record layer: signing and verification (§1.4)
sign_record(record, private_key) -> AtribRecord: §1.4.2: removesignature, JCS-serialize, Ed25519-sign with a 32-byte seed, base64url. Optional fields keep their exact presence/absence (omission ≠ null).verify_record(record, *, now_ms=None) -> bool: §1.4.3, all 8 steps (key decode, signature decode, JCS-minus-signature Ed25519 verify (or the creator'ssigners[]entry over §1.7.6 cross-attestation bytes for transaction records),spec_version,event_typeURI validity, timestamp not >5 min future,context_idshape).now_msinjects the clock for corpus tests; defaults to wall time. ReturnsFalseon any failure, never raises.sign_transaction_record(record, private_key, counterparty_signers=None) -> AtribRecord: signs the §1.7.6 cross-attestation bytes; the creator's signer entry comes first, followed by caller-supplied counterparty entries over the same canonical bytes.sign_transaction_attestation(record, private_key) -> SignerEntry: one counterparty signer entry over an existing transaction record's bytes; raisesValueErrorfor non-transaction records.get_public_key(private_key) -> bytes: raw 32-byte Ed25519 public key for a 32-byte seed.
Record construction
build_and_sign_emit_record(*, private_key, event_type, context_id, chain_root, content, informed_by=None, provenance_token=None, annotates=None, revises=None, tool_name=None, args_hash=None, result_hash=None, timestamp_ms=None) -> AtribRecord: the port of@atrib/emit's pipeline: syntheticcontent_idfromSYNTHETIC_SERVER_URL+ the event-type leaf, the D099 defaultargs_hash, lexicographically sortedinformed_by, and omission-not-null optional fields. Pure aside from signing; no I/O;timestamp_msinjects the clock.SYNTHETIC_SERVER_URL:"mcp://atrib-emit", a frozen historical constant (embeds the original package name; MUST NOT change, or old records stop being content_id-compatible).content_hash(content) -> str: the D099 default args commitment:sha256:<hex(SHA-256(JCS(content)))>.leaf_of_event_type_uri(uri) -> str: trailing path segment for atrib-namespace URIs; the URI itself for slash-less or trailing-slash inputs.
Chain composition (§1.2.3 / §1.2.3.1)
genesis_chain_root(context_id) -> str:"sha256:" + hex(SHA-256(UTF-8(context_id))).chain_root(parent_record) -> str: chain_root for a non-genesis record (hash of the parent's canonical signed form).resolve_chain_root(*, context_id, inbound_record_hash_hex=None, auto_chain_tail_hex=None, mirror_tail_hex=None, env=None) -> str: the bit-for-bit D067 port. Precedence, highest first: (1) inbound propagation token hex, (2) within-process auto-chain tail, (3)ATRIB_CHAIN_TAIL_<context_id>env var (accepted only as exactsha256:<64-hex>; malformed falls through), (4) mirror tail (bare 64-hex; caller pre-filters by context_id), (5) synthetic genesis. Pure and synchronous; pass a stubenvin tests.
Hashes and tokens
sha256(data) -> bytes.record_hash_bytes(record) -> bytes/record_hash_hex(record) -> str/record_hash_ref(record) -> str: SHA-256 over the JCS-canonical COMPLETE signed record includingsignature, as raw bytes, bare 64-hex, andsha256:<64-hex>reference form respectively.derive_provenance_token(upstream) -> str: §1.2.6: base64url (no padding) of the first 16 bytes of the upstream record hash; always 22 characters.encode_token(record) -> str/decode_token(token) -> DecodedToken | None: the §1.5.2 propagation token (base64url(record_hash) + "." + base64url(creator_key), max 87 chars). Decoding is lenient per D018: malformed tokens returnNone(meaning genesis), never raise.DecodedTokenis a frozen dataclass of two 32-byte values.
Canonicalization (§1.3)
jcs(value) -> bytes: RFC 8785 via therfc8785package; raisesValueErrorsubclasses on non-I-JSON input (see the boundary section below).canonical_signing_input(record): JCS withsignatureremoved (§1.4.2).canonical_record(record): JCS of the complete signed record (the record-hash preimage).canonical_cross_attestation_input(record): JCS withsigners: []and no top-levelsignature(§1.7.6).
Content identity (§1.2.2)
compute_content_id(server_url, tool_name) -> str:"sha256:" + hex(SHA-256(UTF-8(normalized + ":" + tool))).normalize_server_url(url) -> str: reproduces the WHATWG-parser behaviors the TS implementation relies on (special-scheme slash collapsing and required hosts, default-port dropping, opaque-host case preservation, trailing-slash trim, query/fragment drop), with the same lowercase fallback for unparsable input.
Submission (§2.6.1 / §5.3.5)
validate_submission(record, *, now_ms=None) -> ValidationResult: client-side parity with the log's submission checks (spec_version, event_type URI, integral non-negative timestamp within the server's 10-minute future-skew window, context_id shape, required string fields,sha256:<64-hex>shapes,session_token/informed_bytypes).ValidationResultis a frozen dataclass(ok, status, error).now_msinjects the clock.SubmissionQueue(log_endpoint=None, *, timeout_s=5.0): fire-and-forget submitter on a bounded daemon worker thread.submit(record, priority="normal")never raises; retry is exponential backoff, max 3 attempts inside a 30-second window; 4xx responses are permanent rejects (dropped); transaction records POST with a highX-atrib-Priorityheader. The POST body is the bare signed record, never the mirror envelope (§5.9.4).get_proof(record_hash_bare_hex)reads the proof-bundle cache (keyed by bare hex, nosha256:prefix).flush(deadline_s=30.0)waits, bounded, never raises.DEFAULT_LOG_ENDPOINT:https://log.atrib.dev/v1/entries.normalize_log_endpoint(endpoint) -> str: appends/v1/entriesto a bare origin, mirroring the TS helper.
Keys (§5.6)
resolve_key(env=None) -> ResolvedKey | None: the portable subset of@atrib/emit's ladder:ATRIB_PRIVATE_KEY(base64url 32-byte seed), thenATRIB_KEY_FILE. The macOS-Keychain and 1Password rungs are platform/tool-coupled and intentionally not ported; hosts needing them resolve the seed themselves and pass it explicitly. Never raises: malformed material degrades toNonewith a stderr warning, and absence of a key is pass-through, not an error.ResolvedKey: frozen dataclass:private_key(32-byte seed),source('env' | 'file').
Mirror (§5.9)
MirrorLine: frozen dataclass(record, sidecar, proof, written_at); the normalized view of one mirror line.parse_mirror_line(line) -> MirrorLine | None: tolerates all three §5.9.2 line shapes; malformed lines yieldNone(skip).read_mirror(path) -> list[MirrorLine]: missing file → empty list; a malformed or non-UTF-8 line is skipped, never fatal.read_mirror_tail(path, context_id=None) -> AtribRecord | None: newest record, optionally filtered by context.mirror_tail_hash_hex(path, context_id) -> str | None: bare-hex hash of the newest same-context record, in the shaperesolve_chain_root(mirror_tail_hex=…)expects.append_mirror_line(path, record, *, sidecar=None, proof=None) -> None: appends an envelope line; best-effort (failures warn on stderr). The_localsidecar lives at envelope level, never insiderecord, and never reaches the public log.default_mirror_write_path(env=None):$ATRIB_MIRROR_FILE, else~/.atrib/records/atrib-emit-<agent>.jsonlwith<agent>from$ATRIB_AGENT(defaultclaude-code).default_mirror_read_path(env=None):$ATRIB_AUTOCHAIN_SOURCE, then$ATRIB_MIRROR_FILE, then~/.atrib/records/<agent>.jsonl.
Event types and record shape
SPEC_VERSION:"atrib/1.0".AtribRecord/SignerEntry:TypedDictshapes; optional fields useNotRequiredbecause omission (never null) changes the JCS form and signature.EVENT_TYPE_TOOL_CALL_URI,EVENT_TYPE_TRANSACTION_URI,EVENT_TYPE_OBSERVATION_URI,EVENT_TYPE_DIRECTORY_ANCHOR_URI,EVENT_TYPE_ANNOTATION_URI,EVENT_TYPE_REVISION_URI: the six normative URIs.normalize_event_type(value) -> str: short alias / known typo path → canonical URI; unknown values pass through unchanged.is_valid_event_type_uri(value) -> bool: §1.4.5 syntactic validation (extension URIs pass; the length limit counts UTF-16 code units exactly like the JS reference).is_normative_event_type_uri(uri) -> bool: normative-set membership (informational only).event_type_uri_to_byte(uri) -> int: the §2.3.1 byte mapping; extensions map to0xFF.
Anchor plurality (D138, §2.11.7-§2.11.13)
atrib.anchors is the Python port of the producer-side anchor surface in
packages/mcp/src/anchors.ts. Anchoring never touches signed bytes and
never blocks a write; AtribClient uses this module for its per-anchor
fan-out (see the constructor table above).
ANCHOR_TYPES: the §2.11.8 v1 registry:("atrib-log", "sigstore-rekor", "rfc3161-tsa", "opentimestamps").BUILT_IN_DEFAULT_ANCHOR_SET: the two-anchor zero-config default (§2.11.12 rule 1), value-identical to the TS constant.AnchorDescriptor/AnchorSetConfig:TypedDictconfig shapes (urlwins overendpoint; absentanchor_typemeansatrib-log).resolve_anchor_posture(config) -> AnchorPostureResolution: the pure §2.11.12 precedence rules (default set / ≥ 2 as given /allow_single_anchoropt-in / warn + sidecar marker). Field names match the conformance corpus (spec/conformance/2.11/anchors/). Never raises.resolve_effective_anchors(config) -> list[AnchorDescriptor]: the effective set a producer submits to.anchor_claim_artifact(record_hash) -> bytes: the §2.11.10 claim bytesUTF-8("atrib-anchor/v1:" + record_hash), byte-identical to the TSanchorClaimArtifact; raisesValueErroron a malformed hash (pure builder for programmer input).ANCHOR_CLAIM_PREFIX:"atrib-anchor/v1:".
Attribution receipts (D141, dev.atrib/attribution v0.1)
Consumer-side receipt handling for the MCP extension (see
docs/extensions/dev.atrib-attribution/). Receipts are advisory: trust
derives from verifying signed records, never from the receipt.
ATTRIBUTION_EXTENSION_KEY:"dev.atrib/attribution", the_metakey.ATTRIBUTION_LOG_SUBMISSION_STATUSES:("queued", "submitted", "disabled", "failed"); a queue status, never an awaited proof (§5.3.5).parse_attribution_receipt_block(meta) -> AttributionReceiptBlock | None: lenient extraction from a tool result's_meta: anything malformed yieldsNonewithout raising; wrong-typed fields drop.verify_attribution_receipt(block) -> AttributionReceiptVerification: the extension-spec §6.2 consumer check over the RAW result block (structural well-formedness plus token ↔ receipt ↔ optional-record internal consistency), the exact port of@atrib/mcp'sverifyAttributionReceipt; hostile input yieldsmismatched=["malformed"]. Internal consistency only; Tier-3 assurance additionally verifies the attached record (verify_record) and log inclusion.check_attribution_receipt_consistency(block, record=None) -> AttributionReceiptConsistency: record-side consistency of a parsed block against the signed record it names; no record at all →receipt_valid=False, mismatched_fields=["record"](conservative).
Evidence envelopes (D137, §5.5.7)
atrib.evidence implements the universal envelope, the single
attachment model for external evidence (the legacy protocol string set
is frozen). Envelopes live outside signed bytes. Conformance:
spec/conformance/evidence-envelope/ (all case families).
EVIDENCE_TIERS:("declared", "shape", "attested", "verified");EVIDENCE_REF_KINDS,EVIDENCE_CONSTRAINT_STATUSES: the other closed vocabularies.EvidenceEnvelope,EvidencePayload,EvidencePayloadRef,EvidenceConstraint,EvidenceResult,EvidenceVerifier:TypedDictshapes matching the TSEvidenceEnvelopefamily field-for-field.evidence_envelope_key(envelope) -> str: dedup identity(profile, payload.hash);evidence_tier_rank(tier) -> int:0(declared) …3(verified), unknown tiers-1.validate_envelope(envelope) -> EnvelopeValidation/is_valid_envelope(envelope) -> bool: the normative §5.5.7 shape rules, reason-for-reason with the TS validator (closed reason-code set, e.g.profile_uri,payload_hash,inline_without_inline_kind). Rejecting an envelope never rejects the record it attaches to.build_evidence_envelope(*, profile, tier, ...) -> (envelope | None, warnings): producer-side builder: computespayload.hashfrompayload_material(JCS rule,jcs_sha256) orpayload_material_utf8(raw rule,raw_sha256), fills the defaultresult, validates, and drops the envelope (never the record) on rejection. RaisesValueErroronly on contradictory input.classify_profile(uri, registry=ATRIB_PROFILE_REGISTRY) -> ProfileClassification: full-URI profile identity; a foreign domain reusing an atrib profile name is a valid third-party profile, never the atrib profile.map_legacy_evidence_block(block) -> EvidenceEnvelope(spec-named aliasfrom_legacy_evidence_block): the deterministic legacy §5.5.6 mapping through the frozen five-row table (FROZEN_LEGACY_PROTOCOLS,LEGACY_PROTOCOL_TO_PROFILE); unknown protocols raiseValueError(the one normative MUST-reject).order_envelope_instances(instances): tier desc,checked_at_msdesc, verifier name asc;is_relay_identity_swap(original, relayed): flags a verifier-block-only difference;assess_reproducibility(envelope):verified+ref.kind: "withheld"is well-formed but claimed-not-reproducible;render_envelope_opaque(envelope): the unknown-profile preservation surface (never drop, never affect record validity).jcs_sha256(value)/raw_sha256(text): the two §5.5.7 payload hash rules.
Encoding
base64url_encode(data)/base64url_decode(value): RFC 4648 §5, no padding; decode raisesValueErroron malformed input.hex_encode(data)/hex_decode(value): lowercase hex.
Contracts honored
- §5.8 degradation: operational failures never raise and never block:
missing key means pass-through, network failures are silent with bounded
retry (3 attempts / 30s window), all warnings carry the
atrib:prefix. The only raise paths are contradictory inputs. - §1.2.3.1 chain composition:
resolve_chain_rootis a bit-for-bit port of the D067 reference (packages/mcp/src/chain-root.ts), tested againstspec/conformance/1.2.3/multi-producer/. - §5.9 mirror conventions: JSONL envelopes under
~/.atrib/records/, all three line shapes tolerated on read,_localsidecar never enters signed bytes or the public log. - §2.6.1 submission: bare signed record POST, priority header, idempotent-safe retry, proof bundles cached by record hash.
Scope (v0)
The write verb (attest) signs in-process; recall covers the
history/session_chain shapes over the local mirror. Anchor plurality
(D138)
fans out to every usable atrib-log anchor; registered non-atrib-log
anchor types count toward the posture but have no Python transport yet
(their legs are skipped with a warning. The TS reference stubs them
too). atrib.evidence implements the
D137
envelope surface (validation, builder, legacy mapping, tier semantics)
and atrib.attribution the
D141
receipt checks. Daemon-first transport
(Streamable HTTP to the local primitives runtime) lands with the
post-2026-07-28 stateless MCP transport rather than reimplementing the
current initialize-handshake session protocol. Summarize is not an SDK
verb. Synthesis belongs to the calling harness.
Known cross-implementation boundary (I-JSON)
Content outside I-JSON (RFC 7493), integers beyond 2^53-1 or strings with
lone UTF-16 surrogates, cannot round-trip between JS and Python: the JS
runtime canonicalizes such content (lossily for big integers, because JS
numbers are already doubles) while this SDK's RFC 8785 implementation
rejects it with a ValueError. Rejection is deliberate: silently
reproducing JS precision loss would corrupt caller data, and a commitment
only one implementation can reproduce is worse than an error. Keep attest
content within I-JSON. The rejection contract is pinned in
tests/test_port_parity.py.
Tests
pip install -e "python/[dev]"
pytest python/tests
mypy # configured in pyproject.toml
Generated API documentation (from the inline docstrings) uses
pdoc, included in the [dev] extras:
python -m pdoc atrib -o docs-build/ # static HTML
python -m pdoc atrib # live server
CI runs the same suites plus the cross-implementation determinism judge on
Python 3.10 and 3.12 via .github/workflows/python-sdk.yml, path-scoped to
the byte-identity surface (python/, packages/sdk/, packages/mcp/,
services/atrib-emit/, spec/conformance/). The judge step fails loudly
if it would silently skip.
The conformance corpora are consumed unmodified from spec/conformance/;
a port failure is a spec-bug discovery, not something to route around.
Part of atrib
atrib is an open protocol for verifiable agent actions. Every action becomes a signed, chain-linked record that anyone can verify against a public Merkle log, with no operator to trust. This package is one entrypoint. See the full package family and the protocol spec.
Project details
Release history Release notifications | RSS feed
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 atrib-0.1.1.tar.gz.
File metadata
- Download URL: atrib-0.1.1.tar.gz
- Upload date:
- Size: 85.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3a053896c3c23e5a027a564e64ac1e3a45492b4b467770d60fc48abe9b9e3dc
|
|
| MD5 |
316c15a6a50bd21ab6616e426918400d
|
|
| BLAKE2b-256 |
4049b4edf3d3ebe4e2eabefd8bab589dc976b49d3a98ea41e0edbe8fedca038f
|
Provenance
The following attestation bundles were made for atrib-0.1.1.tar.gz:
Publisher:
release-pypi.yml on creatornader/atrib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
atrib-0.1.1.tar.gz -
Subject digest:
b3a053896c3c23e5a027a564e64ac1e3a45492b4b467770d60fc48abe9b9e3dc - Sigstore transparency entry: 2120454480
- Sigstore integration time:
-
Permalink:
creatornader/atrib@3a0b764b19b045d4027f30bd14de25545a11c3be -
Branch / Tag:
refs/heads/main - Owner: https://github.com/creatornader
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@3a0b764b19b045d4027f30bd14de25545a11c3be -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file atrib-0.1.1-py3-none-any.whl.
File metadata
- Download URL: atrib-0.1.1-py3-none-any.whl
- Upload date:
- Size: 59.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a9ffa63969a56ec112b389b6e954be25f9e9aad584a49df11e5925af076eaba8
|
|
| MD5 |
b0adb012a692f99b5fc2b686419e4db3
|
|
| BLAKE2b-256 |
ed446dd46e881d1b075d329fb8e69d136210cd9f911803c36d40e8b78c721646
|
Provenance
The following attestation bundles were made for atrib-0.1.1-py3-none-any.whl:
Publisher:
release-pypi.yml on creatornader/atrib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
atrib-0.1.1-py3-none-any.whl -
Subject digest:
a9ffa63969a56ec112b389b6e954be25f9e9aad584a49df11e5925af076eaba8 - Sigstore transparency entry: 2120454825
- Sigstore integration time:
-
Permalink:
creatornader/atrib@3a0b764b19b045d4027f30bd14de25545a11c3be -
Branch / Tag:
refs/heads/main - Owner: https://github.com/creatornader
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@3a0b764b19b045d4027f30bd14de25545a11c3be -
Trigger Event:
workflow_dispatch
-
Statement type: