INTEGRATION-ONLY and KNOWN-LIMITATION are grep-able, but the grep answers the wrong question. Thirty-four Go sites share the two markers and they carry four different meanings: "declared, nothing implements it" reads exactly like "implemented, only its I/O is unreachable from here", and neither reads differently from a limitation that was accepted on purpose and is not coming back. docs/deferred-seams.md sorts them, following the bucketed shape internal/updater/doc.go already uses for its own package rather than starting a second convention. Sorting them turned up two markers that had outlived the condition they describe. config.go called the modpack upload transport a deferred integration after both backends had shipped -- LocalContextStore and S3ContextStore, selected in cmd/felis by the shape of user_uploads_context, with the uploads PVC mounted and the felis-uploads-s3 Secret rendered. What is still deferred is the far end: Kaniko reading that context from inside the build Pod. updater/doc.go listed the `felis update` CLI and the off-cluster Velocity jar read under REMAINING INTEGRATION. Both exist -- cmd/felis/update.go, and gatherer_host.go, which answers Velocity from the installed jar's manifest and felis-api from the running binary's build stamp. The two nil seams that bullet also names are real, but they belong to the in-cluster gatherer only, so the bullet now says which caller has what and which is still empty. The index also records the collision that makes a naive grep misleading: docs/troubleshooting.md uses [INTEGRATION-ONLY] for something else, defined in its own opening at :19 -- the symptom is produced by the kubelet, kaniko or a live handshake, so it cannot be reproduced from the repository. Those twelve marks say where a failure comes from, not that something is unbuilt, and are excluded. Both code changes are comments. Every file:line the index cites was checked against the line it points at.
6.5 KiB
Deferred integration seams
INTEGRATION-ONLY and KNOWN-LIMITATION are grep-able markers in the Go source.
This file is the index of what each one currently means, so that reading the
unfinished face of the system does not require re-deriving it from 34 comment
sites.
It exists for two reasons. The markers do not all mean the same thing — four distinct states share them, and "declared, nothing implements it" reads exactly like "implemented, but its I/O cannot be exercised from this repo". And a marker outlives the condition it describes: two of them were stale when this index was first assembled, both claiming as future work something that had already shipped.
The pattern here is the one internal/updater/doc.go already uses for its own
package — state the verification boundary in buckets, so a green test suite is not
mistaken for a finished integration. This file is the same idea across the whole
tree.
The marker collides with a different vocabulary in troubleshooting.md
docs/troubleshooting.md uses [INTEGRATION-ONLY] for something else, defined in
its own opening at :19: the symptom is produced by the kubelet, kaniko or a live
handshake, so it cannot be reproduced from the repository. Those twelve marks say
where a failure comes from. They are not unfinished work and are not indexed below.
A grep across *.md and *.go returns both sets; only the Go ones are seams.
Declared, nothing implements it
internal/updates/seams.go:32—Notifier.internal/mailsends OTP over SMTP, but nothing adapts it to this interface and no in-game channel exists.felis updatepasses nil deliberately: a human typing the command is the notification.internal/updates/seams.go:43—Applier. Nothing applies an update anywhere. A nil applier is not silent —RunrecordserrNoApplieragainst every planned apply, so a mis-scheduled apply is loud rather than lost.internal/updater/gatherer_integration.go:22— the two current-version seamsNewSysGathererleaves nil, for the in-cluster path: the k8s read of the control-plane Deployment image, and the Velocity jar inspection. Both are answered on the host path (see "Built" below), so this gap is specific to a caller that has a cluster client instead of the node.internal/api/handlers_updates.go:21,28— the maintenance window persists and the API serves it, but the in-cluster CronJob that would hand a real window to a runner does not exist.felis updateruns with a zero window, under which everyScheduledcomponent degrades to a notify, so no path can currently claim an apply is under way.internal/submit/blobstore.go:40— the uploads PVC is mounted into felis-api but not into the Kaniko build Pod, so a submitted context is durable at the derived location without yet being readable by the build that consumes it.
Built; only its I/O is unverifiable from this repo
Code exists and is unit-tested against fakes. What is missing is a host, a cluster or a real upstream account to run it against — not an implementation.
cmd/felis/tui_edge_apply.go:246,274,295— thenftedge fence, its idempotent teardown, and the cloudflared invocation.internal/cfsetup/runner.go:18andinternal/cfsetup/cfsetup.go:329— the real Cloudflare Tunnel and Access API calls;internal/cfsetup/cfsetup_test.go:11drives the whole flow through a fake.internal/api/console.go:39,internal/api/logstream.go:236,internal/api/logstream.go:306,internal/fileedit/k8sjobs.go:45— each needs a live cluster (RCON,pods/logfollow, a Job).internal/api/handlers_access.go:170,490— parsing real vanilla and LuckPerms command output.
Deliberately accepted, not scheduled to close
These are decisions, not backlog. Each names the condition under which it would be worth revisiting.
internal/api/pgrepo.go:281— the quota check andClaimServerare two statements (audit #4 TOCTOU). Closeable only against a real Postgres.internal/api/api.go:671—cooldownLimiteris process-local, so across N api replicas a caller could draw up to N OTP codes per window. The intra-replica burst is closed; cross-replica bounding needs a shared store, out of scope for a single-replica install.internal/submit/submit.go:436andinternal/submit/submit_test.go:351— a post-CASApprovefailure leaves a row indistinguishable from the benign case, soApprovereturns a distinct error naming the running build rather than allowing a blind re-drive that would double-push. The alternative ordering is worse.cmd/felis/tui_edge_apply.go:246, second marker on the same site — the fence targets nftables. On a firewalld host a reload can flush the standalone table; firewalld-native coordination is not handled. A missingnftbinary fails loud rather than leaving the port open.internal/api/handlers_account.go:169— the reclaim "start fresh vs inherit" choice is CODE-ONLY on the Java/Velocity side; the link-status endpoint reports link completion only and does not surface it.
Wired since the marker was written
internal/api/handlers_email_otp.go:54,223,227andinternal/api/api.go:84— SMTP shipped on 2026-07-20 (internal/mail, wired atcmd/felis/api.go:264). The nil-Mailerbranch that logs the code server-side is a runtime fallback for an install with no[smtp]section, not an unbuilt feature. The comments are accurate; the reading "Felis cannot send mail" is not.internal/config/config.go:117— was stale. It described the upload transport as a deferred integration after both backends had shipped (LocalContextStore,S3ContextStore, selected incmd/felis/api.goby the shape of the configured base). Corrected in the change that added this file; what remains deferred is only Kaniko's read, indexed above.internal/updater/doc.go:44— was stale. Its REMAINING INTEGRATION bullet listed thefelis updateCLI and the off-cluster Velocity jar read, both of which exist (cmd/felis/update.go,internal/updater/gatherer_host.go). Corrected in the same change; the two nil seams it also names are real and remain above.
Recorded outside the code
deploy/limbo/README.md:139— no NetworkPolicy locks the minecraft-namespace egress or the control-namespace ingress today, which is why the login pod reachesfelis-api-internal:8081. This is a conditional obligation rather than a seam: if a future deployment adds either lock, it must also open that path. Spec v4.1 §21 asks for those policies;cmd/felis/manifests.gorenders the game-port one.