fix(sdk): versao que o artefato realmente e, e o tipo que o servidor realmente manda (oss-sdk#11, #13, #6) - #124
Open
fabianocruz wants to merge 1 commit into
Open
fix(sdk): versao que o artefato realmente e, e o tipo que o servidor realmente manda (oss-sdk#11, #13, #6)#124fabianocruz wants to merge 1 commit into
fabianocruz wants to merge 1 commit into
Conversation
…realmente manda (oss-sdk#11, #13, #6) - CLI imprimia 0.5.5 sendo 0.6.0, e o User-Agent do Python dizia 0.10.0 sendo 0.11.0 (com um terceiro numero, 0.10.2, no __version__). Uma fonte por pacote, e um teste que a prende ao manifesto publicado. - AgenticReceipt publicado nao declarava seis campos que a API emite sob payment. Só o tipo muda; o recibo e selado e assinado. - Um 201 magro nao vira mais Invalid Date: os fallbacks sao o que a propria chamada pediu, e o backend sempre ganha quando responde. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
fabianocruz
added a commit
that referenced
this pull request
Sep 3, 2026
…/nanoid/qs Unblocks the CI security-audit step, red on every PR since the new advisories landed (same failure on PR #124's run; main's last CI run predates them). Lockfile-only, all within existing semver ranges; turbo build 18/18 and test 36/36 green after the bump. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BtvPxidmzsA22yoVJSWdba
This was referenced Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lane
ent-ossda auditoria, metade SDK. Dois achados inteiros e a metade SDK de um terceiro. Os outros estao emcodespar/codespar-enterprise#895ecodespar/codespar#141, porque nenhum PR atravessa repositorio.Nada aqui publica nem bumpa versao. O que falta publicar esta listado no fim.
oss-sdk#11 — versao mentida em dois artefatos publicados
Mecanismo. Tres lugares escreviam a versao a mao e nenhum conferia os outros.
TypeScript:
packages/cli/src/version.ts:7dizia0.5.5enquantopackages/cli/package.json:3dizia0.6.0. Essa constante alimenta--version, o banner (index.ts:548) e oUser-Agentde toda requisicao (api.ts:56). O proprio cabecalho do arquivo pedia "keep in sync with package.json on release" e nada garantia isso.Python:
packages/python/src/codespar/_http.py:54mandavacodespar-python/0.10.0,__init__.py:144declarava__version__ = "0.10.2"epyproject.toml:7declara0.11.0. Tres valores. Uma requisicao do SDK atual chegava rotulada como um release duas versoes atras, e toda pergunta do lado servidor da forma "qual versao do SDK esta fazendo isso?" era respondida errado.O que mudou. Uma fonte por pacote, e um teste que prende essa fonte ao manifesto publicado, lido em tempo de teste.
0.6.0e o cabecalho aponta para o teste que a mantem honesta.src/codespar/_version.pynovo, com__version__eUSER_AGENT;__init__.pye_http.pyimportam dele. O modulo nao importa nada do pacote, porque__init__importa o transporte e o transporte precisa da versao — qualquer coisa menos isolada e ciclo.Divergencia da proposta da triagem. Ela sugeria
importlib.metadata.version("codespar")para oUser-Agent. Nao fiz, e a razao esta no cabecalho do_version.py: a busca de metadata so responde quando a distribuicao esta instalada, entao precisaria de um literal de fallback de qualquer jeito — acrescenta um ramo em vez de remover a duplicata, e faz a versao que o pacote reporta depender de como ele foi carregado (um checkout de fonte responderia diferente de umpip install). Isso tambem tornaria o proprio teste dependente do ambiente, que e a armadilha 4. O literal unico mais um teste que o prende aopyproject.tomlfecha a deriva no ponto onde ela realmente aconteceu.Para o TS, o mesmo raciocinio no outro sentido:
version.tsnao lepackage.jsonem runtime porquedist/index.jse o bin publicado e subir dedist/atras de um manifesto resolve diferente sob npx, install global e bundler. O literal fica; o teste e o que nao deixa ele separar de novo.Testes.
packages/cli/src/__tests__/version.test.tsepackages/python/tests/test_version.py. O teste de header que ja existia (api.test.ts) afirmava que oUser-Agentcasa com uma forma semver — verdade para qualquer versao, inclusive a errada. Os novos afirmam o valor, contra o manifesto lido em disco, e exercitam a funcao de verdade: o TS captura o header de uma requisicao real doApiClientcomfetchespionado, o Python chamabuild_headersde verdade nos dois ramos (com e semproject_id). Cada um traz um controle de que o manifesto foi de fato lido — sem ele, uma leitura falha comparariaundefinedcomundefined.O que NAO fecha. O
ci.ymldeste repo nao tem job de Python — nao hapytestem lugar nenhum dele. O teste de versao do Python roda localmente (PYTHONPATH=src python3.12 -m pytest tests -q) e nao vai proteger nada no CI ate existir esse job. Acrescentar o job esta fora do escopo deste PR e vale uma issue propria. O lado TS roda no CI, dentro denpx turbo run build typecheck test.oss-sdk#13 — o tipo
AgenticReceiptpublicado e um subconjunto do que a API devolveMecanismo.
packages/types/src/types.ts:519-531e o tipo com que um consumidor do SDK tipa uma resposta decodespar_ledger action=receipt. OreceiptRowToJsondo enterprise (packages/api/src/agentic-receipt.ts:945-996) emite seis campos sobpaymentque a interface nao declarava:amount_atomic,amount_authorized,amount_charged,amount_refunded,meteringesandbox. Um consumidor nao conseguia le-los semas any, e o TypeScript acusava cada um como excedente em qualquer literal.O que mudou. So o tipo. Os seis campos entram como opcionais, com a nulidade que o servidor realmente emite (
amount_atomicvai em todo recibo e enullnum trilho fiat; os outros so aparecem num recibo medido), mais a interfaceReceiptMeteringque faltava. Nenhum byte do que o servidor emite muda, e nao pode mudar: o recibo e selado e assinado, entao "alinhar o JSON com o tipo" quebrariachainereceipt_sig. O tipo se move; o fio nao.Teste.
packages/types/src/agentic-receipt-surface.test.ts. O vermelho e do proprio compilador — a fixture e a forma emitida, campo a campo, comsatisfies AgenticReceipt:O segundo teste e o controle: um recibo fiat, sem nenhum dos campos medidos, continua tipando — sem ele, declarar os seis como obrigatorios passaria o primeiro teste e quebraria todo recibo Pix.
O que NAO fecha, e o que falta publicar. A outra metade do achado fica no enterprise e nao foi feita: subir o pin de
@codespar/types(packages/api/package.json:98, hoje0.10.14) e marcar o literal dereceiptRowToJsoncomsatisfies AgenticReceipt. Isso depende de um publish:0.10.15— a versao que este repo declara — ja esta na registry, entao estes campos precisam sair em0.10.16. O bump de versao e onpm publishsao acao publica do Fabiano e nao estao neste PR. Ordem: bumparpackages/types/package.jsonpara0.10.16, publicar, depois subir o pin no enterprise e acrescentar osatisfiesla.oss-sdk#6 — metade SDK: um 201 magro nao pode virar Invalid Date
Mecanismo.
packages/core/src/session.ts:148-151. O runtime MIT devolvia{ id, status }no 201 (consertado emcodespar/codespar#141), e o SDK montava a sessao direto desse corpo.new Date(undefined)nao lanca: e um Invalid Date que formata como "Invalid Date", compara falso com tudo e serializa para null.user_ideserverschegavamundefineddo mesmo jeito. E em:594-606,cachedTools = payload.toolsguardavaundefinedquando a chave faltava — um cache que nunca enche.Vale registrar o alcance real:
createdAt,userIdeserversexistem no objeto concreto mas nao na interface publicaSession, entao um consumidor TypeScript nao chega neles e um de JavaScript chega. Foi assim que um Invalid Date ficou ali sem ninguem ver.O que mudou. O piso do proprio SDK, para que um backend que responde magro degrade para um valor verdadeiro em vez de um quebrado. Nada e inventado:
userIdeserverscaem para o que esta chamada pediu, ecreatedAtpara o instante em que a resposta chegou — dentro de um round trip do horario real de criacao.cachedToolscai para a lista vazia uma vez, em vez de?? []escondendo o problema em cada call site. EBackendSessionResponse/BackendConnectionsResponsepassam a declarar esses campos como opcionais: a opcionalidade e uma afirmacao sobre o que este codigo precisa sobreviver, nao sobre o que um backend correto manda.Teste.
packages/core/src/__tests__/session-shape-tolerance.test.ts. O controle e a metade que importa: quando o backend manda os campos, o backend ganha. Um fallback que sobrescrevesse o servidor em silencio seria um bug pior que o consertado.O que NAO fecha. A metade runtime esta em
codespar/codespar#141. A suite de contrato compartilhada (packages/types/src/testing/contract-suite.ts:325) continua so afirmando "id e connected" emconnections()— foi essa assercao fraca que deixou a divergencia passar, e alarga-la obriga o runtime gerenciado ao mesmo criterio, entao ficou fora deste PR.Estado real do CI
O CI deste PR esta VERMELHO em 5 jobs, e nenhum deles e o trabalho deste PR. Run 33183207992.
O job
ci— o que rodanpm ci+npx turbo run build typecheck test— passou em todos os passos menos o ultimo:O
Security auditenpm audit --omit=dev --audit-level=high. Este PR nao muda nenhuma dependencia:git diff main -- package.json package-lock.json packages/*/package.jsone vazio. As duas advisorieshighsao deip-address, uma dependencia transitiva, e reproduzem identicas nomainlocal com o mesmo lockfile (3 vulnerabilities (1 moderate, 2 high)). O ultimo run verde domainfoi no mesmo commit base (08d2cc1) e antes destas advisories serem publicadas — ou seja, omainde hoje fica vermelho aqui tambem. Nao consertei: bumpar dependencia transitiva nao e o achado desta lane e mudaria o lockfile no meio do congelamento.Os outros quatro sao os quatro jobs de exemplo que apontam para
ghcr.io/codespar/codespar:main, e falham todos no mesmo ponto, antes de qualquer codigo deste PR rodar:Os tres jobs de exemplo que usam
ghcr.io/codespar/codespar:latest—skeleton,nfse-from-natural-language,whatsapp-installment-negotiation— passaram. A divisao e exatamente por tag de imagem, e o container morre no boot, antes de tocar em SDK. A imagem:mainfoi publicada pela ultima vez em 2026-08-22 e omaindocodespar/codesparandou desde entao. Isso e um problema da imagem, nao deste diff, e vale uma issue propria — nao consegui consertar daqui.Local, neste clone, no commit deste PR:
npx turbo run build typecheck test: 54 tasks successful, 54 totalpackages/python:PYTHONPATH=src python3.12 -m pytest tests -q→118 passed, 8 skipped. Este comando nao e rodado pelo CI (nao ha job de Python), e isso e um buraco que este PR nao fecha.Reversao conferida
main(teste mantido)packages/cli/src/version.ts_http.py+__init__.py,_version.pyremovidopackages/types/src/types.tstsc --noEmit: 8 errospackages/core/src/session.tsO que falta publicar (acao do Fabiano)
@codespar/types@0.10.16— bump empackages/types/package.jsonenpm publish. Sem isso o enterprise nao pode subir o pin nem acrescentar osatisfies AgenticReceipt, que e a outra metade do oss-sdk#13.@codespar/cli@0.6.0— este PR so faz o codigo dizer 0.6.0; se a 0.6.0 ja estiver publicada com a string 0.5.5 dentro, e preciso um republish (0.6.1) para o artefato na registry parar de mentir.codespar(PyPI) 0.11.0 — mesma coisa: oUser-Agentso fica certo no artefato publicado depois de um novo build.🤖 Generated with Claude Code