Skip to content

docs: stop the per-service pages promising the opposite of what the code does - #167

Merged
skyoo2003 merged 2 commits into
mainfrom
docs/resync-service-pages-with-code
Sep 13, 2026
Merged

skyoo2003 merged 2 commits into
mainfrom
docs/resync-service-pages-with-code

Conversation

@skyoo2003

Copy link
Copy Markdown
Owner

Summary

The five per-service pages under docs/services/ were last touched on 2026-04-18. Four of them describe a DevCloud that no longer exists, and they fail in the direction that costs a reader the most: their Known Limitations lists deny features that are now implemented. Someone reads "No batch operations" and writes the workaround for a BatchWriteItem that has worked for months.

Operation tables are now derived from internal/generated/fidelity — the hand-verified tier per service, the same source the coverage gates read — rather than from memory.

Changes

Operation tables re-derived

Page Documented Hand-verified Wrongly listed as absent
s3.md 8 37 Multipart upload, CORS, bucket policy, ACL, versioning, tagging, ListObjectsV2, CopyObject, DeleteObjects, HeadBucket
dynamodb.md 8 20 UpdateItem, batch, transactions, GSI/LSI, streams, TTL, conditional writes, filter/projection expressions
lambda.md 6 25 Versions, aliases, event source mappings, resource-based policies
iam-sts.md 6 (IAM) 58 (IAM) + 4 (STS) Groups, inline policies, instance profiles, tagging, the delete/update half of the user and role lifecycle; STS was missing GetAccessKeyInfo

sqs.md was already current and is untouched.

Limitations rewritten around what is actually load-bearing

The same shape recurs in three services: a sub-resource round-trips faithfully and changes nothing. S3 stores a versioning status without assigning version IDs, stores ACLs and bucket policies without ever denying a request, and stores CORS without emitting an Access-Control-* header. Lambda accepts a resource-based policy it never evaluates. IAM stores policy documents nothing parses. Each is now stated as stored, not evaluated at the operation that stores it — a green response is exactly what makes it dangerous.

Lambda's headline limitation survives unchanged because it is still true: Invoke returns a fixed placeholder and the handler never runs. It is now stated with the response body, since nothing in the shape of that reply distinguishes it from a real one and a test asserting on the status code alone passes against code that did not execute. The event source mapping rows say what they really do — the SQS and DynamoDB stream pollers run, build the AWS-shaped event, and POST it to that stub.

Two storage-layer claims were wrong

  • DynamoDB is SQLite, not BadgerDB. internal/storage/ contains only sqlite/, and badger appears in neither go.mod nor go.sum. README.md, docs/configuration.md and docs/contributing.md were pointing new service authors at a dependency the tree does not have.
  • docs/configuration.md documented three config keys that do not exist — services.lambda.runtime, services.lambda.warm_containers, services.iam.enforce_policies. config.ServiceConfig has exactly two fields, and parse() uses a non-strict yaml.Unmarshal, so writing one of those is dropped in silence. That is the failure mode config.go already grew a warning for on auth.enabled; this stops advertising the keys and says plainly that a knob outside the table does nothing.

Files Changed

File Change
docs/services/s3.md Modified — operation table, notification behaviour, limitations
docs/services/dynamodb.md Modified — backend, attribute types, operation table, limitations
docs/services/lambda.md Modified — operation table, event source mapping behaviour, limitations
docs/services/iam-sts.md Modified — IAM/STS operation tables, limitations
docs/configuration.md Modified — removed three phantom config keys, corrected DynamoDB backend
docs/contributing.md Modified — storage backend guidance for new services
README.md Modified — DynamoDB backend

Testing

  • go test ./cmd/devcloud/ — green. The published-figure gates were re-run: 431/426, the fidelity shares and the 1,530-test suite each re-derived and already agreed with the binary, so no gated number was touched.
  • make docs-build — green. 903 internal links across 24 pages all resolve.
  • Every claim written here was checked against the source it describes rather than against the previous page: the fidelity manifest for operation tiers, each provider's HandleRequest dispatch for behaviour, config.ServiceConfig for config keys, and internal/storage/ plus go.mod for backends.

Related Issues

None.

…ode does

The five per-service pages were last touched on 2026-04-18. Four of them
describe a DevCloud that no longer exists, and they fail in the direction that
costs a reader the most: their "Known Limitations" lists deny features that are
now implemented, so someone reads "No batch operations" and writes the
workaround for a BatchWriteItem that has worked for months.

The operation tables are now derived from internal/generated/fidelity — the
hand-verified tier per service, which is the same source the coverage gates
read — rather than from memory:

  - S3: 8 operations documented, 37 hand-verified. Multipart upload, CORS,
    bucket policy, ACL, versioning, tagging, ListObjectsV2, CopyObject,
    DeleteObjects and HeadBucket were all listed as absent.
  - DynamoDB: 8 documented, 20 hand-verified. UpdateItem, batch, transactions,
    GSI/LSI, streams, TTL, conditional writes and filter/projection expressions
    were all listed as absent.
  - Lambda: 6 documented, 25 hand-verified. Versions, aliases, event source
    mappings and resource-based policies were all listed as absent.
  - IAM/STS: 6 IAM operations documented, 58 hand-verified. Groups, inline
    policies, instance profiles, tagging and the whole delete/update half of
    the user and role lifecycle were listed as absent. STS was missing
    GetAccessKeyInfo.

SQS is the one page that was already current and is untouched.

What replaces those lists is the limitation that is actually load-bearing, and
it is the same shape in three services: a sub-resource round-trips faithfully
and changes nothing. S3 stores a versioning status without assigning version
IDs, stores ACLs and bucket policies without ever denying a request, and stores
CORS without emitting a single Access-Control header. Lambda accepts a
resource-based policy it never evaluates. IAM stores policy documents nothing
parses. Each is now stated as "stored, not evaluated" where the operation is
listed, because a green response is exactly what makes it dangerous.

Two claims were wrong about the storage layer rather than the API surface:

  - DynamoDB is SQLite, not BadgerDB. internal/storage/ contains only sqlite/
    and badger appears in neither go.mod nor go.sum, so README.md,
    configuration.md and contributing.md were pointing new service authors at a
    dependency the tree does not have.
  - configuration.md documented three config keys that do not exist:
    services.lambda.runtime, services.lambda.warm_containers and
    services.iam.enforce_policies. config.ServiceConfig has exactly two fields,
    and parse() uses a non-strict yaml.Unmarshal, so writing one of those is
    dropped in silence. That is the failure mode config.go already grew a
    warning for on auth.enabled; the fix here is to stop advertising the keys
    and say plainly that a knob outside the table does nothing.

Lambda's headline limitation survives unchanged because it is still true —
Invoke returns a fixed placeholder and the handler never runs. It is now stated
with the response body, since nothing in the shape of that reply distinguishes
it from a real one, and a test asserting on the status code alone passes
against code that did not execute. The event source mapping rows say what they
really do: the SQS and DynamoDB stream pollers run, build the AWS-shaped event
and POST it to that stub.

Numbers that a gate already owns were not touched. The 431/426 figures, the
fidelity shares and the 1,530-test suite were each re-derived and already
agreed with the binary.
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Sep 13, 2026
@skyoo2003
skyoo2003 merged commit 7ed51de into main Sep 13, 2026
9 checks passed
@skyoo2003
skyoo2003 deleted the docs/resync-service-pages-with-code branch September 13, 2026 12:26
skyoo2003 added a commit that referenced this pull request Sep 13, 2026
…e fragments

The 400-character ceiling was wide enough to hold two full sentences plus a
subordinate clause, so it never pushed against the one-sentence rule it was
meant to back — the #163 fragment reached 484 and still read as being in
the spirit of the limit. At 200 the ceiling and the rule push the same way.

Refits the eight unreleased fragments that were over. What came out is
detail the linked issue already carries: the eight service names in #161,
the CI-runner timing in #163, the DynamoDB and Lambda operation counts in
#167.

Also trims RELEASE.md's "right length" example, which was 203 characters
and would have failed the limit the paragraph above it states, and labels
both examples with their length.
skyoo2003 added a commit that referenced this pull request Sep 13, 2026
…g to 200 (#168)

* fix: give six changelog fragments the issue link the release tag checks

Six fragments wrote `Issue:` at the top level instead of under `custom:`,
where `.changie.yaml` declares it. `changie batch` rendered them as
`[#<no value>](.../issues/<no value>)`, which release.yml:234 rejects — the
tag would have failed at the notes-validation step, after the guardrails
had already passed.

The pre-flight grep in RELEASE.md (`grep -L 'Issue: "[0-9]'`) matches both
spellings, so it did not catch this.

Also trims the #163 fragment from 484 to 337 characters, under the 400-char
ceiling `.changie.yaml` sets and `changie new` enforces on fragments it
writes itself. The CI-runner timing detail it dropped is in the issue.

* docs: correct the two protocol-table rows that miscount EC2 as having no model

The protocol table said 12 services have no in-tree Smithy model and exactly
one speaks a protocol the parser cannot read. Counted against
internal/generated/fidelity/manifest_gen.go, it is 11 and two: `ec2` is
model-backed but speaks `aws.protocols#ec2Query`, which parser.go:441-453
does not recognise alongside the five it does.

That put the page at odds with fidelity-manifest.md:106 and
compatibility-policy.md:78, which both say 11, and left a core service's
missing engine coverage unexplained. Rows now sum to 431 either way, so the
arithmetic did not expose it, and no test gates this table.

Adds a paragraph separating what EC2 loses from what a registered-only
service loses: EC2 is served by a hand-written provider and is not in the
registered-only five, but its model-declared tail stays `unimplemented`
rather than falling back to `auto-crud`.

* docs: halve the changelog body ceiling to 200 characters and refit the fragments

The 400-character ceiling was wide enough to hold two full sentences plus a
subordinate clause, so it never pushed against the one-sentence rule it was
meant to back — the #163 fragment reached 484 and still read as being in
the spirit of the limit. At 200 the ceiling and the rule push the same way.

Refits the eight unreleased fragments that were over. What came out is
detail the linked issue already carries: the eight service names in #161,
the CI-runner timing in #163, the DynamoDB and Lambda operation counts in
#167.

Also trims RELEASE.md's "right length" example, which was 203 characters
and would have failed the limit the paragraph above it states, and labels
both examples with their length.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant