Skip to content

docs: record the internal auth boundary and why a 403 proves nothing - #25

Merged
piekstra merged 1 commit into
mainfrom
tax-documents
Aug 12, 2026
Merged

docs: record the internal auth boundary and why a 403 proves nothing#25
piekstra merged 1 commit into
mainfrom
tax-documents

Conversation

@piekstra

Copy link
Copy Markdown
Owner

What & why

Tax-season tooling needs lofty documents list / documents download. Before
writing them I tried to dogfood the two catalogued endpoints,
/taxdocuments/v2/all and /taxdocuments/v2/zip-documents. They cannot be
reached from this CLI
, and the reason is structural rather than a missing
feature — so this PR is docs-only. Shipping the command group would have meant
a command that returns 403 for every user, backed by fixtures invented rather
than captured.

What blocks it:

  • Both routes live on the internal surface, behind a website Cognito
    session. GET and POST, anonymous and with the SDK Bearer key, all return
    403. api --internal sends no credential by design.
  • The SDK API key and the website session are unrelated credential systems, and
    the key's only permission axis is trading — there is no documents or tax
    scope to switch on.
  • The public SDK has no document route at all. Across @loftyaicode/sdk
    0.2.0–0.2.4 there are 19 routes (properties, orders, account, amm,
    lp-rewards); searching the bundle and its type definitions for
    tax/1099/K-1/document/download/statement/zip/pdf yields no functional hit.
    Nothing was published and later withdrawn. There is no OpenAPI spec and no
    developer docs site.
  • Lofty's help center documents tax forms as a dashboard-only feature.

The trap worth the writeup: a 403 from this API proves nothing. A gated
route and a path that certainly does not exist return byte-identical
{"message":"Forbidden"}, unchanged even by a malformed Authorization header
(a Cognito authorizer would normally answer 401). So the API cannot be probed
for route discovery, and a 403 never means "exists but forbidden" — we cannot
even confirm the two taxdocuments paths are live, only that nothing we can
send reaches them.

That also settles the catalog's status: it is a static harvest of the website
bundle, records no HTTP method, and cannot be verified by probing. Rather than
hand-edit the @generated src/catalog.rs, the caveat is recorded in
docs/api.md and AGENTS.md, keeping this PR free of code changes.

User-visible changes

None — documentation only. No commands, flags, or schema tags added or
changed. New docs/api.md; README.md and AGENTS.md point at it.

Follow-ups, both recorded in the doc:

  1. Bump cli-common off the pinned v0.1.2. Upstream HEAD adds the
    documents/v1 profile (pk-cli-documents) fixing the canonical spelling
    documents list + documents download <ID> -o <PATH> and the
    document-list/v1 / document-download/v1 /
    document-download-batch/v1 DTOs. Bump before any document support is
    written here, so this CLI adopts the family shape instead of inventing one.
    Deliberately not attempted in this PR.
  2. Observe the real shapes. Reaching /taxdocuments/v2/* needs an
    interactive session at a logged-in browser. Response shapes are currently
    entirely unobserved, and fixtures must be scrubbed captures — never invented
    to fit an assumed shape. If getZipFile returns a pre-signed URL, that URL
    is a live credential and never lands in a fixture or a commit.

Checklist

  • make verify passes locally (fmt + clippy + tests + smoke)
  • Tests added/updated (fixtures load from disk; no live-API calls in tests)
    — n/a, no code change; the existing suite still passes
  • No secrets, keys, real account ids, balances, or addresses in the diff
    (including fixtures — dummies only)
  • Any new mutation confirms and honors --force (exit 6 when non-interactive)
    — n/a, no mutations
  • Docs/README updated if behavior changed

Tax-season tooling wanted `lofty documents list/download` over the two
catalogued `taxdocuments/v2` routes. They cannot be reached from this CLI,
and the reason is structural rather than a missing feature — so write down
the finding instead of shipping a command that would 403 for everyone.

- `/prod/taxdocuments/v2/*` lives on the internal surface, behind a website
  Cognito session. GET and POST, anonymous and with the SDK Bearer key, all
  return 403. The API key and the website session are unrelated credential
  systems, and the key's only permission axis is trading — there is no
  documents or tax scope to enable.
- The public SDK has no document route at all: across `@loftyaicode/sdk`
  0.2.0–0.2.4 there are 19 routes (properties, orders, account, amm,
  lp-rewards) and no tax/document/download route was ever published. Lofty's
  help center documents tax forms as a dashboard-only feature.
- The trap that cost the most time: a gated route and a route that certainly
  does not exist return byte-identical `{"message":"Forbidden"}`, unchanged
  even by a malformed Authorization header (a Cognito authorizer would answer
  401). So a 403 never means "exists but forbidden", and this API cannot be
  probed for route discovery.

That last point also settles the catalog's status: it is a static harvest of
the website bundle, records no HTTP method, and cannot be verified by probing.
AGENTS.md and the README now say so.

Follow-ups noted in the doc: bump cli-common off v0.1.2 to pick up the new
documents/v1 profile (pk-cli-documents) before any document command is
written, so this CLI adopts the family spelling rather than inventing one;
and observing the real response shapes needs an interactive browser session,
since fixtures must be scrubbed captures and never invented.
@piekstra
piekstra requested a review from piekstra-dev August 12, 2026 03:45

@piekstra-dev piekstra-dev left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated PR Review

Reviewed commit: a9b1cb43c862
Profile: reviewer - Posting as: piekstra-dev

Summary

Reviewer Findings
documentation:docs 0
policies:conventions 0
structure:repo-health 0

Reviewer Coverage

Reviewer Status Inspected Skipped Constraints
documentation:docs complete_broad README.md, docs/api.md unavailable unavailable
policies:conventions complete_broad AGENTS.md, docs/api.md unavailable No local convenience copies of the shared cli-common/docs or .github breadcrumbs were present in the review context, so this reviewer could not check the new AGENTS.md/docs/api.md text against those canonical docs for duplication or drift.
structure:repo-health complete_broad AGENTS.md, docs/api.md unavailable unavailable

0 PR discussion threads considered. 0 summarized; 0 resolved.


Completed in 2m 20s | $1.36 | claude-sonnet-5 | cr 0.10.268
Field Value
Model claude-sonnet-5
Reviewers documentation:docs, policies:conventions, structure:repo-health
Engine claude_cli · claude-sonnet-5
Reviewed by cr · piekstra-dev
Duration 2m 20s wall · 3m 57s compute
Cost $1.36
Tokens 90 in / 14.7k out

Per-workstream usage

Workstream Model In Out Cache read Cache create Cost Duration
orchestrator-selection claude-sonnet-5 6 1.0k 55.6k 12.5k $0.11 16s
documentation:docs claude-sonnet-5 24 3.1k 426.9k 28.7k $0.35 47s
policies:conventions claude-sonnet-5 32 6.5k 529.2k 24.6k $0.41 1m 51s
structure:repo-health claude-sonnet-5 22 3.7k 381.2k 35.2k $0.38 52s
orchestrator-rollup claude-sonnet-5 6 406 65.6k 15.0k $0.12 9s

@piekstra
piekstra merged commit 25321ed into main Aug 12, 2026
2 checks passed
@piekstra
piekstra deleted the tax-documents branch August 12, 2026 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants