Target.Webhook and Webhook.Targets form a reference cycle that will recurse once anything marshals a preloaded model #177
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Raised by the independent review of #174. Deliberately NOT milestoned 1.0.0 — it cannot fire today.
internal/database/model_target.go:37givesTargetaWebhookback-reference, andWebhookhasTargets. That is a cycle.encoding/jsondoes not detect cycles; it recurses until the stack dies.It is harmless right now for two reasons that both happen to hold rather than being designed to:
omitzerohides the back-reference while it stays zero, and nothing in the service marshals these models at all —/api/v1is registered and empty. The first handler that marshals a preloadedWebhookorTargetwill recurse.The reviewer described it as deliberate-looking, and it may well be — GORM needs the association for preloading. This issue is not asking to remove it, only to make the safety explicit rather than incidental.
Definition of done
Webhook(withTargetspopulated) and a preloadedTarget(withWebhookpopulated) is either safe or impossible, and a test pins whichever it is.json:"-"on the back-reference, confirm GORM's preloading is unaffected — GORM does not use json tags for association mapping, but verify rather than assume, and check nothing round-trips these models through JSON in tests or fixtures.internal/database/for the same shape while you are there, and list what you found.Related context: #160 added
json:"-"toTarget.Config,APIKey.KeyandSetting.Valuefor the adjacent reason — thatTargetViewis the masking barrier for the HTML path only, and the first handler to marshal a model directly would leak. This is the same "the models are not safe to marshal yet, and nothing marshals them" territory, so it may be worth doing both audits at once when someone picks up/api/v1.Implementation requirements
next, PR based onnext, single commit, title ending(closes #N).TODO.md(see #112).make bootstrapin a fresh clone before gating — browser assets are fetched at build time, andmake lintnow needs Docker.make checkplus the Docker lint path with the cache defeated. All linting runs in Docker, never on the host.