GuardianContext
Nome: GuardianContext (decidido em 17/09/2026; antes "AgentNexusPlatform", nome já tomado por outro produto). Pacote
guardiancontext, CLIguardian, envGUARDIAN_*, estado local em.guardian/e~/.guardian/. Marca da IronStack.Status: em produção —
https://api.ironstack.dev.br(FastAPI + PostgreSQL/pgvector, Caddy/HTTPS), rodando a revisão de 17/09 com billing validado no sandbox da Asaas (docs/trabalho/billing-sandbox-e2e-2026-09-17.md). VM renomeada em 17/09 (/opt/guardiancontext, containersguardiancontext-*, banco/usuárioguardiancontext, envGUARDIAN_*).
Produto: transformar em SaaS o protocolo de coordenação multi-agente (roteador + wiki por tópico + decisões + quadro de trabalho) validado dentro do repositório GymAi Pro entre 06/09/2026 e 14/09/2026. Este documento é o handoff — tudo que foi decidido numa sessão de ideação longa, pra continuar aqui sem arrastar aquele histórico nem misturar com o desenvolvimento do app.
Instalar
Uma linha, sem falar com ninguém — instala o uv se faltar, o pacote
guardiancontext[semantic,desktop] (Python 3.11) e abre o Desktop Manager, onde você
cria a conta (com aceite dos Termos de Uso) e conecta o repositório:
irm https://api.ironstack.dev.br/install.ps1 | iex # Windows (PowerShell)
curl -fsSL https://api.ironstack.dev.br/install.sh | sh # macOS / Linux
Passo a passo para quem vai testar: docs/guia-do-testador.md.
Só terminal: uv tool install --python 3.11 "guardiancontext[semantic]" e guardian signup.
Licença e termos
Software sob licença proprietária de uso (LICENSE); o serviço, os planos e os avisos sobre
programação com agentes de IA estão em docs/termos-de-uso.md
(versão 2026-09-20, aceita no cadastro). Contato: suporte@ironstack.dev.br.
Por que isto é um produto
O GymAi Pro roda com várias sessões de IA (Claude Code, Codex, Cursor, Kimi) editando a mesma árvore git ao mesmo tempo. Isso já causou perda de commit, furo de segurança (~40 min aberto) e horas de diagnóstico errado. A solução — uma base de conhecimento em markdown versionada no git (router → wiki por tópico → decisões → quadro de trabalho), mais um manual de sobrevivência pra git compartilhado — funcionou bem o suficiente pra virar tese de produto: com o volume de vídeos no YouTube propondo variações do mesmo problema (memória persistente pra IA de código), esta solução, medida, saiu na frente.
Documentos de referência publicados (Claude Artifacts — acessíveis fora deste projeto, independente de onde a conversa aconteceu):
- Kit de Coordenação Multi-Agente — os dois prompts vendáveis: o Instalador (bootstrap da estrutura em qualquer repo) e o Auditor (disciplina recorrente, o que vira assinatura).
- Infra do Kit de Coordenação — topologia Oracle (quente) × Locaweb (fria), schema MySQL completo, plano de implementação em 7 fases, funil de onboarding do cliente.
Decisões já tomadas (não reabrir sem motivo novo)
- Não centralizar o artefato de coordenação em si.
router.md/wiki//decisoes//quadro continuam sendo arquivo, na árvore do cliente — é isso que dá zero-setup, diff em PR e funcionamento offline. Avaliamos e descartamos mover isso pra MySQL (recriaria o erro do "ai-memory"/Akita: segunda fonte de verdade divergindo do git). - O que centraliza: biblioteca de padrões curada pela empresa (não pelo cliente), dashboard de auditoria hospedado, licenciamento. Nunca o conteúdo bruto do cliente (incidente, decisão, segredo de arquitetura).
- Modelo de acesso ao repo do cliente: Agente instalado (CLI local) primeiro, GitHub App como possível "modo enterprise" depois — não o contrário.
- Licenciamento nunca por chamada de ferramenta. Validação 1×/sessão ou 1×/dia, com cache e graça offline. Isto é lição paga: o hook
PreToolUsedo graphify custava ~400ms por chamada de Bash/Grep/Read/Glob, aplicado à árvore inteira — medido e revertido em 13/09/2026 no próprio GymAi Pro. - Banco: PostgreSQL (SaaS) + SQLite (agente local). Revogado o MySQL. O PostgreSQL é a base única do servidor — ACID, JSONB compacto, FTS nativo (
tsvector) e busca vetorial viapgvectorpara recuperação top-k (minimiza tokens), migrations via Alembic, replication/arquivamento. O SQLite (FTS5 + sqlite-vec) é apenas cache/índice offline do agente local, derivado do Git — nunca uma segunda fonte de verdade. Tabelas desenhadas por padrão de acesso, não por entidade pura. - Topologia: tudo que responde uma sessão em andamento (API, Redis, PostgreSQL primário) fica na VM Oracle, como mais um serviço no
docker-compose.ymlque já rodahermes-agent/hermes-support. Sem arquivo frio em fornecedor separado: o PostgreSQL é a base única, e o arquivamento/retenção sai de replicação e particionamento na própria instância — não de uma segunda infraestrutura com deploy manual. - Funil: cadastro → instalação local (funciona offline, nunca bloqueia) → primeiro valor imediato (auditoria roda na hora da instalação, dashboard não nasce vazio) → loop recorrente (hook de git ou cron do cliente) → conversão free→pago via Asaas (gatilho: 2º repositório) → equipe (licença por repositório instalado, não por pessoa). Trial de 14 dias revogado em 20/09/2026 (
decisoes/2026-09-20-plano-free-um-repositorio.md): a instalação nasce no planofree, sem prazo, limitado a 1 repositório por conta; o gatilho por tempo saiu. - Locaweb como arquivo frio: REVOGADA em 14/09/2026. A decisão de usar a Locaweb como destino de arquivo frio (deploy manual cPanel/FTP, nginx/PHP na frente, risco de
413silencioso eREMOTE_ADDR/HTTPSnão confiáveis) foi abandonada. Substituto definido: PostgreSQL (SaaS) + SQLite (agente local), conforme a decisão #5.
Números medidos que sustentam o pitch (não são estimativa)
TRABALHO_EM_ANDAMENTO.mddo GymAi Pro chegou a 245 KB (~66 mil tokens) em 14 dias — 43% de uma janela de 200k gastos antes de abrir um arquivo de código. Reestruturado (quadro = stub de 6 linhas, história emdocs/trabalho/<slug>.md) para 20 KB (~5,6k tokens), 11,8× menor.- Hook
PreToolUsedo graphify: ~400ms por chamada de ferramenta, medido, removido. - Graphify (grafo de código) no mesmo repo: 144,3× de redução de token por consulta, medido via
graphify benchmark. - Divergência normal entre
mainlocal eorigin/mainnum repo com múltiplas sessões de IA cherry-pickando cada uma o próprio commit: 83 vs. 71 commits, quase tudo mesmo conteúdo com SHA diferente — isso é o comportamento esperado do fluxo, não bug (lição aprendida depois de eu mesma ler errado da primeira vez).
Em aberto — próximos passos de ideação/execução
- Nome final do produto (este README usa "GuardianContext" como nome da pasta/projeto; não foi validado como nome comercial).
- Piloto: usar o próprio GymAi Pro como conta zero, comparando os números acima como caso de referência real.
Estado da implementação (Fases 1–4 — núcleo local + backend + licenciamento + produção)
Implementado, testado e deployado em produção (https://api.ironstack.dev.br).
Núcleo local (guardiancontext — pacote Python instalável)
Control plane Git-native. pip install -e . expõe o comando guardiancontext:
guardian init [--mode shared|branches]— bootstrap idempotente da estrutura (router, quadro, wiki, decisões, claims, handoffs, histórico) e do modo de trabalho (ver "Modos de trabalho").guardian doctor— valida a estrutura; falha com exit≠0 se houver erro. Reporta o modo e se o hook está instalado.guardian hook install|uninstall— hookpre-commit(ver "Hook de pre-commit").guardian audit— auditoria determinística (sem LLM): arquivos ausentes, quadro inchado, claims expirados/conflitantes, handoffs abandonados, links quebrados.guardian claim --actor X <escopo...>— reserva de escopo de arquivos com TTL; recusa sobreposição de outro ator.guardian release <id>— libera um claim.guardian handoff create/accept— handoff com aceite único (segundo accept é recusado).guardian index rebuild/search— índice SQLite híbrido (FTS5 + vetores) derivado dos markdown. Rebuild incremental por sha256: só re-embedda páginas novas/alteradas e expurga as removidas (8 páginas sem mudança → 0.2s; antes ~5s).--semanticforça o modelo;--lexicaldesativa; default é automático. Busca combina FTS5 + cosine com RRF (Reciprocal Rank Fusion).guardian signup [--api-url URL] [--email E] [--name N] [--repo NOME] [--invite CODIGO]— o caminho normal de entrada (20/09/2026, sem admin): cria a conta (senha viagetpass, sem eco, nunca em argumento), a primeira instalação (repositório = nome da pasta atual, licençafree) e gravaapi_url+api_keyexatamente como oconfigure. Pergunta o que faltar; sem TTY e sem os argumentos, falha com a mensagem do flag.api_urldefault:https://api.ironstack.dev.br. 402 (limite do plano), 403 (convite obrigatório), 409 (e-mail já cadastrado), 429 (rate limit) viram uma linha legível. O JWT vive só na memória do comando — o que fica em disco é a API key.guardian login [--api-url URL] [--email E] [--repo NOME] [--yes]— entra numa conta existente: lista as instalações; com uma (ou--repo), oferece reemitir a chave e gravar aqui (as chaves antigas continuam valendo); sem nenhuma, cria a primeira (mesmo fluxo dosignup). 401 = "e-mail ou senha inválidos", sem traceback.guardian configure --api-url ... --api-key ...— o caminho manual: grava uma chave emitida pelo admin (POST /installations) ou por outrologin.guardian sync-patterns— sincroniza os patterns do índice local com o servidor. Privacidade (decisão #2): envia apenas slug/título/sha256/embedding — nunca o corpo dos documentos. Upsert idempotente por sha256 no servidor (repository_patterns), com remoção de páginas deletadas.guardian report [--actor X]— roda a auditoria e envia o relatório (métricas apenas) ao servidor; offline-safe (enfileira se o servidor estiver fora).guardian embed <texto>— gera embedding local de 384 dimensões. Dois modos: semântico (--semantic, usaparaphrase-multilingual-MiniLM-L12-v2viafastembed, 100% local, funciona bem em português) ou hashing determinístico (--hashing, sem modelo externo). Auto-detecta o melhor disponível.guardian license [--force]— consulta o estado da licença (validação 1×/dia, com cache e graça offline — decisão #4).guardian contribute <arquivo.md> [--yes] [--tags a,b]— propõe uma decisão/regra deste repo à biblioteca curada. Única saída de corpo de documento (decisão #2): anonimiza localmente, mostra o texto inteiro e pede confirmação (sem TTY exige--yes), envia com embedding gerado no mesmo recorte do índice. Sem fila offline. Oreportavisa quando hádecisoes//wiki/novas ou alteradas desde o anterior (.guardian/last_report.json) — só aponta o comando, nunca envia.guardian proposals list [--status pending|approved|rejected|all] [--json]/show <id> [--json]/approve <id> [--slug s] [--tags a,b]/reject <id> --reason "..."— o lado do curador do laço de aprendizado: lista a fila (default pendentes; id, status, slug, repo/data, tamanho do corpo), mostra título/tags/corpo completo (já anonimizado), aprova (só metadados editáveis — slug e tags; o corpo sobe como foi lido; imprime o slug do pattern publicado) ou rejeita com motivo obrigatório. Usa aapi_urldoconfigure, mas o token admin vem só deGUARDIAN_ADMIN_TOKEN(nunca gravado em config, nunca impresso); sem a variável, sai com erro. 401/404/409 viram mensagens legíveis, sem traceback.
Testes: pytest tests/ — 137 testes (59 + 21 de modos/hook + 17 de proposals + 29 de signup/login + 9 do desktop; 10 pulam sem fastembed/PySide6) (os de embedding semântico pulam se fastembed não estiver instalado). Embedding oficial: fastembed==0.5.1 (pinado); vetores de outra versão do fastembed não são comparáveis (0.5.1 × 0.8.0 deram cosseno 0,565 para o mesmo texto).
Modos de trabalho
Várias sessões de IA num repositório trabalham de um de dois jeitos, e o que é
normal num é sinal de erro no outro. O modo é declarado em router.md (linha
Modo: shared ou Modo: branches) — versionado, portanto visível para todas as
sessões — e lido de lá pelo doctor e pelo hook. Não fica em .guardian/config.json
porque isso é local a uma working copy.
shared(default): várias sessões editam e comitam a mesma working copy.initgrava owiki/como-trabalhar.mdcompleto — as regras de árvore compartilhada nascidas de incidente (nuncagit add -A, nuncastash/restore ., branch+log antes de cada commit, cópia entre worktrees apaga, etc.).branches: cada sessão numa worktree/branch própria; a principal só recebe merge.init --mode branchesgrava uma versão enxuta: sincronize a principal antes de criar a branch, uma branch por sessão/tarefa (guardian claimcontinua avisando o escopo), nunca copie arquivo entre worktrees (cherry-pick), merge só por PR ou fast-forward, nunca--forcena principal, claims/handoffs/quadro continuam sendo o canal entre sessões. As regras que independem do modo ficam ("verde não prova completude", "está na principal se prova por conteúdo").
guardian init sem --mode respeita o modo que o router.md já declara; com --mode
troca a linha do router (migração). O como-trabalhar.md de um repo já instalado nunca
é sobrescrito — trocar de modo depois é editar esse arquivo à mão. guardian doctor
imprime [MODO] … e avisa se o router não declara modo.
Hook de pre-commit
guardian hook install grava um pre-commit (em .git/hooks/, ou onde core.hooksPath
apontar) de poucas linhas de sh POSIX — roda no Git Bash do Windows e em Linux/macOS — que
chama guardian hook run pre-commit. O trabalho fica em Python. A cada commit:
- Imprime
[guardian] branch=<x> head=<sha7> arquivos=<n>— a regra "branch + log antes de cada commit" cumprida pelo hook, não pela memória do agente. - Recusa se algum arquivo em staging está num claim ativo de outro ator. O ator da
sessão vem de
GUARDIAN_ACTOR(recomendado: uma variável por sessão), deguardian hook run pre-commit --actor Xou deactorem.guardian/config.json. Sem ator, avisa e não bloqueia por claim. - No modo
shared, recusa staging largo: mais de N arquivos (default 25;guardian hook install --max-files N,GUARDIAN_HOOK_MAX_FILESouhook_max_filesna config) e nenhum claim do próprio ator cobre todos eles — o sinal degit add -Anuma árvore compartilhada. No modobranchesisso é normal e não é checado.
O escape é o do git, git commit --no-verify; não existe outro. Instalar duas vezes não
duplica (o bloco fica entre marcadores); um pre-commit de outra origem que seja shell
script recebe o bloco no fim e uninstall remove só o bloco; se não for shell (python,
node…), a instalação recusa e diz o que fazer.
Desktop Manager (guardian-desktop, 20/09/2026)
GUI em PySide6 no mesmo pacote (extra desktop; pacote guardiancontext_desktop/). É o que o
instalador de uma linha abre: assistente de primeira execução (Criar conta com aceite dos Termos
/ Entrar → pasta do repositório git → modo → roda init, hook install, index rebuild,
report, license com log na tela → resumo) e janela principal (conexão, licença, repositórios
da conta, busca de patterns, "Instalar em outro repositório"). Uma configuração só: usa as
mesmas funções do CLI (guardiancontext.account, sync.configure) e a mesma
~/.guardian/config.json; só tema/pastas ficam em ~/.guardian/desktop.json. Senha nunca em
disco, JWT só em memória. Sem binário (sem assinatura de código). Detalhes:
guardiancontext_desktop/README.md.
Backend (FastAPI + PostgreSQL + pgvector + FTS + Alembic)
backend/app/— API em FastAPI, SQLAlchemy 2.0 + psycopg.- Modelos:
users,repositories,audit_events,api_keys,licenses,billing_events,patterns(biblioteca curada comembedding vector(384)+search_vector tsvector),pattern_proposals(fila de propostas doguardian contribute). - Busca full-text em português (
to_tsvector/websearch_to_tsquery) e vetorial (cosine_distancevia pgvector) sobre os padrões curados. - Migrations Alembic (inclui
CREATE EXTENSION vector). - Autenticação (Fase 2): endpoints admin protegidos por
GUARDIAN_ADMIN_TOKEN(fail-closed se vazio); endpoints do agente protegidos por API key (api_keys, SHA-256). Instalação viaPOST /api/v1/installationsemite a chave uma única vez. - Self-service (20/09/2026):
POST /auth/registeré público (rate limit em memória, 5/h por IP;GUARDIAN_SIGNUP_INVITE_CODEnão vazio exigeinvite_code→ 403) e exige o aceite dos Termos de Uso:terms_versionigual asettings.terms_version(422 caso contrário), gravado emusers.terms_version/terms_accepted_at.GET /termos(markdown, fora do/api/v1) serve o texto eGET /api/v1/termos/versaoa versão. Os instaladores de uma linha também saem daqui:GET /install.ps1eGET /install.sh(backend/app/static/). Com o JWT:POST /me/installations(repo + chave + licençafree, 402 no limite — mesma função interna do/installations),GET /me/installations(lista com plano/status, sem chaves),POST /me/installations/{id}/keys(reemite chave do próprio repo; 404 se não for dele; as antigas continuam válidas — revogação segue admin/SQL). - Licenciamento (Fase 3): a instalação nasce no plano
free— licençaativo, sem prazo, 1 repositório por conta (POST /installationse/installations/fullrespondem 402 no segundo; plano criado sob demanda pelo código, sem migration). Segundo repositório exige assinatura ativa em plano pago via/checkout— vale então omax_repositoriesdo plano (None= ilimitado). Repositóriosinternalnão contam. Validação 1×/sessão ou 1×/dia (GET /api/v1/license), com cache e graça offline no agente (decisão #4). Licença por repositório (decisão #7). Licençastrialantigas continuam vencendo na data. - Licença interna (sem cobrança):
POST /repositories/{id}/license/grant(admin) → planointernal, ativa sem prazo, fora do Asaas. Para os projetos do próprio dono e cortesias. - Billing Asaas (Fase 3): webhook
POST /api/v1/billing/webhookautenticado pelo "Token de autenticação" do painel (headerasaas-access-token, comparação em tempo constante, 503 semGUARDIAN_ASAAS_WEBHOOK_TOKEN). A Asaas não assina o body. Idempotente poriddo evento; responde 200 a todo payload válido (evento irrelevante →ignored), porque fora de 2xx a Asaas reenvia. Casa a licença porpayment.subscription/subscription.idcontraasaas_subscription_id. Mapeamento embackend/app/services/asaas.py. Ainda não validado com um evento real — o webhook no painel está inativo até o deploy. - Dashboard (Fase 3):
GET /dashboard(HTML) +GET /api/v1/dashboard/summary(métricas apenas — repositórios, usuários, auditorias, licenças por status, auditorias recentes; nunca conteúdo bruto). docker compose up -d dbsobepgvector/pgvector:pg16;docker compose up apisobe a API.- Login JWT:
GUARDIAN_JWT_SECRETpróprio (separado do admin token), fail-closed; senha em bcrypt; admin token comparado em tempo constante.POST /installations/fulle a leitura da biblioteca curada (GET /patterns,/patterns/search,/patterns/similar) exigem admin token ou API key. - Testes:
backend/.venv/Scripts/python -m pytest backend/tests/(precisa de Postgres +GUARDIAN_JWT_SECRET) — 71 passam. CI em.github/workflows/ci.yml: suíte do CLI, uma head no Alembic, migrations num banco vazio e no estado de produção, suíte do backend.
O que ainda NÃO existe (fora do corte até a Fase 4)
- GitHub App (modo enterprise) — ainda só o agente local (decisão #3).
- Publicação no PyPI (pacote validado: build + twine check + smoke em venv limpo; conta criada, token salvo em
guardiancontext.pypirc; faltatwine uploadcom credenciais do usuário).
Laço de aprendizado — o produto aprende com quem usa (20/09/2026)
A biblioteca curada cresce com decisões reais dos repositórios instalados, sem quebrar a decisão #2: o report compara decisoes/ e wiki/ com o report anterior e só avisa (guardian contribute <caminho>); o dono roda o comando, lê o texto já anonimizado e confirma. O servidor recebe em POST /api/v1/patterns/proposals (API key do repo), roda o anonimizador de novo e recusa com 422 se sobrar identificador; a proposta fica pending em pattern_proposals. Um admin lista (GET /patterns/proposals?status=pending), lê (GET /patterns/proposals/{id}), aprova (POST .../{id}/approve, com edições opcionais — vira Pattern com FTS e o vetor da proposta; a resposta traz pattern_slug) ou rejeita (POST .../{id}/reject, nota obrigatória) — pelo CLI, guardian proposals list|show|approve|reject com GUARDIAN_ADMIN_TOKEN no ambiente. Lista de identificadores proibidos em guardiancontext/anonymizer.py (cópia verificada por teste em backend/app/services/anonymizer.py). Registro: docs/trabalho/laco-de-aprendizado-2026-09-20.md.
Produção (Fase 4 — deploy + webhook + instalação)
Deployado e validado em produção na VM Oracle (Ubuntu ARM64):
https://api.ironstack.dev.br— API FastAPI + Postgres/pgvector viadocker compose, atrás do Caddy (HTTPS/Let's Encrypt automático,caddy reloadsem downtime). Subdomínioapi.ironstack.dev.braponta para a VM via DNS A na Locaweb.- Webhook Asaas cadastrado no painel, inativo: URL
POST /api/v1/billing/webhook, API v3, envio não sequencial, token de autenticação gerado. Ativar só depois do deploy do handler novo (o anterior exigia HMAC, que a Asaas não envia — recusaria 100% dos eventos). - Instalação de produção criada: repo
GuardianContext(id=1), ownerrogerio@ironstack.dev.br(id=1), API keygc_…emitida viaPOST /api/v1/installations. - CLI local conectado:
guardian doctor→ 0 erros;guardian index rebuild→ 8 páginas indexadas, embeddings semânticos funcionando (paraphrase-multilingual-MiniLM-L12-v2viafastembed, 100% local);guardian index search "webhook HMAC validation"→ top-k com snippets e similaridade cosine. - Configuração do CLI:
guardian signup/guardian login(ou, manualmente,guardian configure --api-url ... --api-key ...) gravamapi_urlem<repo>/.guardian/config.jsone a API key em~/.guardian/config.json(0600) — nunca dentro do repositório; chave que apareça no config do repo é ignorada. Precedência:GUARDIAN_API_KEY/GUARDIAN_API_URLno ambiente >~/.guardian> repo.GUARDIAN_HOMEredireciona o diretório do usuário (testes/CI).
O guia operacional completo (deploy Docker, variáveis, setup admin, instalação do agente, publicação no PyPI, webhook Asaas, backup, modelo de ameaças) está em docs/runbook-producao.md.
Como retomar uma sessão aqui
Leia este README primeiro — ele substitui a necessidade de reler a conversa original (que ficou no repositório GymAi Pro, sessão longa de 06 a 14/09/2026). Os dois artefatos linkados têm o conteúdo completo de prompts/schema/plano; não precisam ser recriados.
Release files for guardiancontext 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| guardiancontext-0.1.3.tar.gz | 128.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| guardiancontext-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 239.0 kB
Release files / guardiancontext-0.1.3.tar.gz
| Download URL | guardiancontext-0.1.3.tar.gz |
|---|---|
| Size | 128.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
da3fde0dbd21e8b7a46956cce6e5ad65d7f2238477ce5184d46b135c983fe2f6
|
|
BLAKE2b-256 checksum How to use checksums |
37211b86fc08790ea4620c94174e3fd44bde2ce927d28c7c9dfe6d07ccc14523
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency logRelease files / guardiancontext-0.1.3-py3-none-any.whl
| Download URL | guardiancontext-0.1.3-py3-none-any.whl |
|---|---|
| Size | 110.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1851ebfcfa6f5793be7b1aac7a9f748956cb08a00243d4f72f791cacd59e8cb8
|
|
BLAKE2b-256 checksum How to use checksums |
446f439544847f01804739f44e4dc2660e54c4a673611551a1f5e7041761fcdd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 26, 2026.
Transparency log