Files
pulse/internal/api
rcourtman e885b8aced Undo only the links that hold a reported source in report-merge (#2780)
## Problem

A source-filtered `POST /api/resources/{id}/report-merge` picked the
links to undo by each fold's `Sources`, which is the folded side's whole
subtree. Two consequences:

- In a chain (Docker host linked into an agent linked into a VM), naming
only `docker` also split the agent from the VM, because the agent's fold
lists the Docker source it took in.
- Where recorded links form a cycle (S->V, W->V, S->W with V primary),
naming only `vmware` excluded V-W but left W-S, so W rejoined through S
on the next rebuild. `main` cannot record that cycle today (its third
link is skipped once W is folded), so this half is proved on hand-built
folds and will matter once chains record their closing links.

## Change

- `ManualLinkFold` records what each side is on its own (`HolderOwn`,
`FoldedOwn`), read before the other side is merged in. A repeated pair
unions them, as it does `Sources`.
- `ReportedManualLinkFolds` undoes the links that join a member carrying
a reported source to the part that stays, or to another reported member.
A member that hangs below a reported one and carries no reported source
goes with it, and its link stays. "The part that stays" is what the
resource still reaches without passing through a reported member, so a
reported member is cut from every link that would rejoin it.
- The handler uses it in place of `selected(fold.Sources...)`.

A report naming every source, or none, still undoes every link. The
drawer's Split sends every merged source, so it is unchanged; only API
callers with a real `sources` filter see a difference. No schema,
storage or response change.

## Proof

- `TestResourceReportMergeSourceFilterDetachesChainMembers`
(resourceapi): a Docker host linked into an agent linked into a VM,
reported for the leaf, the holder, both, every source and no filter,
checked on the monitor and the REST listing and against the links left
in the store.
-
`TestContract_ResourceReportMergeSourceFilterKeepsLinksOfUnreportedMembers`
(api).
- `TestReportedManualLinkFoldsDetachMembersCarryingTheSource` and
`TestReportedManualLinkFoldsLeaveNoReportedMemberJoined`
(unifiedresources): trees, the cycle above, the root re-keyed, folds
without own sources, a refold that gained a source. The second checks
that no reported member stays joined to the root; selecting by subtree
sources fails it on the cycle.
- Fold recording tests updated for the own sources; clone test checks
they are deep-copied.
- Negative controls on pulse-dev with the handler restored to the
subtree selection: the leaf case of the chain test and the new contract
test both fail with the full split they used to produce.
- Full `internal/unifiedresources` and `internal/api/resourceapi`
packages pass on pulse-dev.
2026-10-10 09:17:04 +01:00
..
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-08-31 19:47:01 +01:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-04-26 17:26:16 +01:00
2026-01-22 00:30:15 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-03-18 16:06:30 +00:00
2026-09-01 01:02:17 +01:00
2026-03-18 16:06:30 +00:00

Internal API Package

This directory contains the API server implementation for Pulse.

Important Note About frontend-modern/

The frontend-modern/ subdirectory that appears here is:

  • AUTO-GENERATED during builds
  • NOT the source code - just a build artifact
  • IN .gitignore - never committed
  • REQUIRED BY GO - The embed directive needs it here

Frontend Development Location

👉 Edit frontend files at: ${PULSE_REPOS_DIR}/pulse/frontend-modern/src/

Why This Structure?

Go's //go:embed directive has limitations:

  1. Cannot use ../ paths to access parent directories
  2. Cannot follow symbolic links
  3. Must embed files within the Go module

This is a known Go limitation and our structure works around it.