kids

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 30, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package kids parses, decomposes, assembles, and round-trip-verifies VistA KIDS (Kernel Installation & Distribution System) distribution files. It is a faithful Go port of py-kids-vc (github.com/rafael5/py-kids-vc, v0.1.0), which in turn ports Sam Habiel's XPDK2VC architecture. The decompose/assemble/ round-trip contract and the KIDComponents/ layout are unchanged from the Python tool.

The round-trip guarantee is semantic equality after line-2 canonicalization, NOT byte-for-byte: routine line 2's volatile patch-list/date/build-number pieces are stripped (see CanonicalizeRoutineLine2), exactly as XPDK2VC and py-kids-vc do. Roundtrip compares the re-parsed builds, not raw bytes.

Index

Constants

View Source
const (
	// RestoreExact: byte-identical to the pre-image, line 2 included.
	RestoreExact = "exact"
	// RestoreProvenanceDrift: command lines (the checksum surface) are byte-identical
	// — so the national checksum (CHECK1^XTSUMBLD / RSUM, both line-2-blind) matches
	// the FORUM gold — but line 2 differs, so the patch-history provenance is wrong.
	RestoreProvenanceDrift = "command-clean-provenance-drift"
	// RestoreDrift: a COMMAND line differs (or a line was added/removed) — the
	// checksum surface itself is broken, the restore did NOT reinstate the routine.
	RestoreDrift = "drift"
)

Foreign-restore verdicts (D4) — the three outcomes RoutineRestoreVerdict grades a restored declared-foreign routine into, in increasing severity.

View Source
const (
	FieldFreeText = "free text"
	FieldNumeric  = "numeric"
	FieldDate     = "date"
	FieldSet      = "set of codes"
	FieldPointer  = "pointer"
)

Field type names — the five scalar shapes a multi-field DD emitter grounds against real KIDS exports (see filecomp_test / coverage-analysis §8). They map to the ^DD definition node's piece-2 type spec.

Variables

This section is empty.

Functions

func BChecksum added in v0.6.0

func BChecksum(lines []string) string

BChecksum renders a routine's recomputed line-2-blind checksum as the "B<n>" string a KIDS transport stores (and the install-attestation record carries as a routine's before/after value). It is the recompute side of VerifyRoutineChecksum.

func CanonicalizeRoutineLine2

func CanonicalizeRoutineLine2(line2 string) string

CanonicalizeRoutineLine2 applies the diff-stability transform to a routine's `;;version` line: keep `;;VERSION;PACKAGE` (pieces 1–4), blank pieces 5 and 6 (the patch list, date, and Build N — volatile on every install). Port of canonicalize_routine_line2.

func DecomposeBuild

func DecomposeBuild(build *Build, outDir string) error

DecomposeBuild decomposes one build's parsed data into a per-component file tree under outDir. Faithful port of decompose_build: no IEN substitution (subscripts preserved exactly); routine line 2 IS canonicalized.

func HashPairs added in v0.6.0

func HashPairs(pairs []Pair) string

HashPairs returns a deterministic sha256 (hex) over a build's ENGINE-relevant pairs — EnginePairs(pairs), i.e. everything except v-pkg's private ("VPKG",…) metadata (so the hash node and any foreign-overwrite declaration are excluded, and the hash is stable whether or not the input is already stamped). Each pair is rendered as a canonical `(<subs>)=<value>` line; lines are sorted so pair order does not matter. This is the deterministic identity of the routine source a restore re-applies.

func MString

func MString(v string) string

MString renders v as an M string literal, doubling embedded quotes: `a"b` → `"a""b"`. It does NOT chunk for the 255-char M line limit — callers that may emit long routine lines must guard or split (see MaxMLine).

func PatchDescriptorToDir

func PatchDescriptorToDir(desc string) string

PatchDescriptorToDir maps an install name to its directory name (VMTEST*1.0*1 → VMTEST_1.0_1), XPDK2VC's PD4FS convention.

func RoutineChecksumB added in v0.6.0

func RoutineChecksumB(lines []string) int64

RoutineChecksumB computes VistA's "new" (line-2-blind) routine checksum over a routine's source lines — a bug-for-bug port of $$SUMB^XPDRSUM (≡ ^%ZOSF("RSUM1")):

S Y=0 F %=1,3:1 S %1=line(%),%3=$F(%1," ") Q:'%3
  S %3=$S($E(%1,%3)'=";":$L(%1), $E(%1,%3+1)=";":$L(%1), 1:%3-2)
  F %2=1:1:%3 S Y=$A(%1,%2)*(%2+%)+Y

Line 2 (the ;;version/patch-list line KIDS rewrites at install) is excluded; a line with no space terminates the count (as in the M, where an empty line past the end makes $F return 0). A single-";" comment line contributes only its leading tag (everything before the first space); a ";;" line and code lines contribute in full. The recomputed value byte-matches the B<n> a real .KID carries, so a mismatch is a corrupted/tampered routine.

func RoutineDriftMatch added in v0.2.0

func RoutineDriftMatch(shipped, live []string) bool

RoutineDriftMatch reports whether a shipped routine and a live routine are the SAME code, ignoring the volatile second line (the `;;`-version/patch-list line KIDS rewrites at install with real checksums/patch history). It canonicalizes line 2 of each (CanonicalizeRoutineLine2) before comparing — so a patch that is still applied matches, and a later national patch that overwrote it does not.

func RoutineRestoreVerdict added in v0.6.0

func RoutineRestoreVerdict(shipped, live []string) string

RoutineRestoreVerdict grades how faithfully a restored routine matches its pre-image, STRICTER than the line-2-blind RoutineDriftMatch (D4). It is the national-overwrite verify mode: a declared-foreign routine (e.g. XWBPRS) must come back byte-identical on its COMMAND lines — every line except line 2, which is exactly the surface both VistA checksums hash — and ideally byte-identical on line 2 too (its patch-history provenance). Returns RestoreExact / RestoreProvenanceDrift / RestoreDrift.

func VerifySidecarHash added in v0.6.0

func VerifySidecarHash(b *Build) (stored string, ok bool, present bool)

VerifySidecarHash is the package-level form over a *Build (see sidecarHash).

func WriteKID

func WriteKID(installNames []string, buildsPairs map[string][]Pair, outPath string) error

WriteKID serializes builds back to KIDS distribution text. Port of write_kid.

func ZeroMatch added in v0.6.0

func ZeroMatch(expected, live string, volatile []int) bool

ZeroMatch reports whether a live stored 0-node matches the one a build shipped, comparing ^-piece by ^-piece and skipping the volatile indices (the pieces FileMan rewrites at install — a pointer resolved to its site IEN, a set-of-codes external resolved to internal). Trailing empty pieces equal absent ones (FileMan trims them), so a shipped "NAME^^^" matches a stored "NAME". An empty live 0-node never matches — it signals the record is absent.

Types

type Build

type Build struct {
	// contains filtered or unexported fields
}

Build is one install's parsed subscript→value data. It is an insertion- ordered map (mirroring a Python dict): a repeated subscript overwrites the prior value but keeps its position, and iteration order is insertion order.

func (*Build) Components added in v0.6.0

func (b *Build) Components() []Component

Components returns one Component per registered entry type (entryTypeByFile) the build ships, ordered by file number for deterministic output — the registry-driven replacement for the eleven per-type XxxNames() accessors the verify/uninstall scripts used to take as positional arguments.

func (*Build) EntryContents added in v0.6.0

func (b *Build) EntryContents() []EntryContent

EntryContents returns one EntryContent per shipped KRN entry record (every entry type, in build order), read from the top-level "KRN",<file>,<seq>,0) 0-nodes with each type's storage global + transform mask attached. The presence probe answers "does a record by this name exist"; this is what lets verify answer "is the record we shipped the record that got filed."

func (*Build) FileContents added in v0.6.0

func (b *Build) FileContents() []FileContent

FileContents returns one FileContent per shipped FILE field-definition node — the top-level ("^DD",<file>,<file>,<fld>,0) image nodes (the file number is DOUBLED in the transport image), with .01 and every typed field. The presence probe answers "does ^DD(file,0) exist"; this is what lets verify assert the DD content matches the build.

func (*Build) FileNumbers added in v0.2.0

func (b *Build) FileNumbers() []int64

FileNumbers returns the FileMan file numbers shipped by the build, read from the bare ("FIA",<file>) section nodes — what `v pkg verify`/`uninstall` use to probe and back out each installed file.

func (*Build) ForeignRoutines added in v0.6.0

func (b *Build) ForeignRoutines() []string

ForeignRoutines returns the routines this build declared as foreign overwrites (the embedded ("VPKG","FOREIGN",<name>) nodes), in transport order. This is the OFFLINE signal class-aware uninstall reads from the .KID alone — with no pre-image, a build with foreign overwrites must be REFUSED, never delete-all.

func (*Build) Get

func (b *Build) Get(subs Subs) (string, bool)

Get returns the value for subs.

func (*Build) HL7AppNames added in v0.6.0

func (b *Build) HL7AppNames() []string

HL7AppNames returns the #771 HL7 APPLICATION PARAMETER component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) HLOAppNames added in v0.6.0

func (b *Build) HLOAppNames() []string

HLOAppNames returns the #779.2 HLO APPLICATION REGISTRY component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) HelpFrameNames added in v0.6.0

func (b *Build) HelpFrameNames() []string

HelpFrameNames returns the #9.2 HELP FRAME component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) KeyNames added in v0.6.0

func (b *Build) KeyNames() []string

KeyNames returns the #19.1 SECURITY KEY component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) Len

func (b *Build) Len() int

Len is the number of distinct subscripts.

func (*Build) ListTemplateNames added in v0.6.0

func (b *Build) ListTemplateNames() []string

ListTemplateNames returns the #409.61 LIST TEMPLATE component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) LogicalLinkNames added in v0.6.0

func (b *Build) LogicalLinkNames() []string

LogicalLinkNames returns the #870 HL LOGICAL LINK component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) MailGroupNames added in v0.6.0

func (b *Build) MailGroupNames() []string

MailGroupNames returns the #3.8 MAIL GROUP component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) OptionNames added in v0.6.0

func (b *Build) OptionNames() []string

OptionNames returns the #19 OPTION component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) Pairs

func (b *Build) Pairs() []Pair

Pairs returns the entries in insertion order.

func (*Build) ParamDefNames added in v0.2.0

func (b *Build) ParamDefNames() []string

ParamDefNames returns the #8989.51 PARAMETER DEFINITION component names in build order — what `v pkg verify`/`uninstall` use to probe and back out each definition.

func (*Build) ProtocolNames added in v0.6.0

func (b *Build) ProtocolNames() []string

ProtocolNames returns the #101 PROTOCOL component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) RPCNames added in v0.6.0

func (b *Build) RPCNames() []string

RPCNames returns the #8994 REMOTE PROCEDURE component names in build order — what `v pkg verify`/`uninstall` probe and back out.

func (*Build) RequiredBuildNames added in v0.6.0

func (b *Build) RequiredBuildNames() []string

RequiredBuildNames reads the build's #9.611 Required-Build chain back off its BLD manifest, in sequence order — the `BLD,1,"REQB",<seq>,0)` = `Name^Action` nodes emitRequiredBuildManifest writes. The install-attestation record carries this so an audit shows the prerequisite chain the op declared. nil when the build has none.

func (*Build) RoutineChecksum added in v0.6.0

func (b *Build) RoutineChecksum(name string) string

RoutineChecksum returns the checksum string stored in the build's transport RTN node for routine name — piece 3 of the 2-subscript `"RTN",<name>)` value (`0^<numlines>^<checksum>…`). "" if the build ships no such node. A v-pkg build stores "0" (real checksum computed at install); an ingested foreign .KID stores the real `B<n>`.

func (*Build) RoutineNames

func (b *Build) RoutineNames() []string

RoutineNames returns the build's RTN component names in build order — the 2-subscript `"RTN",<name>` header pairs (the per-routine line nodes have 4 subscripts, the RTN count node has 1). `v pkg verify`/`uninstall` use these to probe and delete each installed routine.

func (*Build) RoutineSource added in v0.2.0

func (b *Build) RoutineSource(name string) []string

RoutineSource returns the shipped source lines of routine name, in line order — the `"RTN",<name>,<n>,0)` pairs collected by ascending n. Empty if the build ships no source for that routine. Used by `v pkg verify --drift` to compare the shipped patch against the live routine.

func (*Build) Set

func (b *Build) Set(subs Subs, value string)

Set assigns value to subs, overwriting any existing entry for the same key.

func (*Build) Sorted

func (b *Build) Sorted() []Pair

Sorted returns the entries ordered by the _sort_key collation.

type BuildInput

type BuildInput struct {
	InstallName    string         // NAMESPACE*VERSION[*PATCH]
	Namespace      string         // NAMESPACE
	Routines       []RoutineSrc   // routine components, in build order
	ParamDefs      []ParamDef     // #8989.51 PARAMETER DEFINITION KRN components
	Options        []Option       // #19 OPTION KRN components (generic entry emitter, B.1)
	Keys           []SecurityKey  // #19.1 SECURITY KEY KRN components (B.1)
	Protocols      []Protocol     // #101 PROTOCOL KRN components (B.1)
	RPCs           []RPC          // #8994 REMOTE PROCEDURE KRN components (B.1)
	MailGroups     []MailGroup    // #3.8 MAIL GROUP KRN components (B.1)
	ListTemplates  []ListTemplate // #409.61 LIST TEMPLATE KRN components (B.1)
	HelpFrames     []HelpFrame    // #9.2 HELP FRAME KRN components (B.1)
	HL7Apps        []HL7App       // #771 HL7 APPLICATION PARAMETER KRN components (B.1)
	HLOApps        []HLOApp       // #779.2 HLO APPLICATION REGISTRY KRN components (B.1)
	LogicalLinks   []LogicalLink  // #870 HL LOGICAL LINK KRN components (B.1)
	Files          []FileDD       // brand-new FileMan FILE DD components (FIA)
	RequiredBuilds []ReqBuild     // Required Builds (#9.611) — prerequisites
	EnvCheck       string         // environment-check routine (bare name) → top-level "PRE"
	PreInstall     string         // pre-install routine entryref → top-level "INI"
	PostInstall    string         // post-install routine entryref → top-level "INIT"
	Platform       string         // VER node (Kernel^FileMan), default "8.0^22.2"
	// ForeignRoutines names routines this build intentionally overwrites that are
	// owned by another package (e.g. VSLRT splicing the national XWBPRS). Each is
	// embedded as a private ("VPKG","FOREIGN",<name>) node so class-aware uninstall
	// can read the declaration OFFLINE from the .KID and refuse to delete a foreign
	// routine it cannot restore. EnginePairs strips these before engine staging, so
	// they never reach KIDS filing — they are v-pkg metadata, not a KIDS component.
	ForeignRoutines []string
}

BuildInput is the normalized input to MakeBuildPairs. Volatile fields are NOT carried (install date/user/real checksums) — the export is byte-identical for identical inputs, the deterministic-build invariant (§7.2 #2).

type BuildReversibility added in v0.2.0

type BuildReversibility struct {
	Build               string             `json:"build"`
	Class               ReversibilityClass `json:"class"`
	ClassName           string             `json:"className"`
	ShipsRoutines       bool               `json:"shipsRoutines"`
	RoutineCount        int                `json:"routineCount"`
	Routines            []string           `json:"routines,omitempty"`
	HasInstallCode      bool               `json:"hasInstallCode"`
	InstallCode         map[string]string  `json:"installCode,omitempty"` // role -> entry tag
	ShipsFileManEntries bool               `json:"shipsFileManEntries"`
	FileManFiles        []string           `json:"fileManFiles,omitempty"` // file numbers with exported entries
	ShipsFileDD         bool               `json:"shipsFileDD"`
	FileDDFiles         []string           `json:"fileDDFiles,omitempty"` // file numbers shipped as a FILE (DD/data)
	// ForeignOverwrites are the routines this build declared (in the .KID) as
	// overwrites of routines owned by another package — the offline signal (F1)
	// that class-aware uninstall must NOT delete them without a pre-image to
	// restore. Read verbatim from the embedded declaration, never inferred.
	ForeignOverwrites []string `json:"foreignOverwrites,omitempty"`
}

BuildReversibility is the per-build static analysis used to drive class-aware install / uninstall / snapshot.

func ClassifyBuild added in v0.2.0

func ClassifyBuild(name string, b *Build) BuildReversibility

ClassifyBuild derives the reversibility of a single parsed build by walking its transport pairs and probing four node shapes (routine name, install-code subnode, exported FileMan entry, FileMan FILE multiple).

type ChecksumResult added in v0.6.0

type ChecksumResult struct {
	Name     string          `json:"name"`
	Stored   string          `json:"stored"`             // the .KID's stored checksum (e.g. "B51345879" or "0")
	Computed string          `json:"computed,omitempty"` // the recomputed value (B-format only)
	Verdict  ChecksumVerdict `json:"verdict"`
}

ChecksumResult is one routine's checksum verdict.

func ChecksumMismatches added in v0.6.0

func ChecksumMismatches(results []ChecksumResult) []ChecksumResult

ChecksumMismatches returns just the results that failed verification (the refuse set). An empty slice means every shipped, checksummed routine verified (or there was nothing to verify).

func VerifyBuildChecksums added in v0.6.0

func VerifyBuildChecksums(b *Build) []ChecksumResult

VerifyBuildChecksums grades every routine the build ships, in build order.

func VerifyRoutineChecksum added in v0.6.0

func VerifyRoutineChecksum(stored string, lines []string) ChecksumResult

VerifyRoutineChecksum grades a stored checksum against the routine's shipped source. Only a "B<n>" stored value is recomputed (the format KIDS ships); "0"/"" is skipped (v-pkg build), and any other form is unknown-format (cannot verify → not a tamper).

type ChecksumVerdict added in v0.6.0

type ChecksumVerdict string

ChecksumVerdict grades one routine's transport-checksum check.

const (
	// ChecksumOK: the recomputed B-checksum matches the .KID's stored value.
	ChecksumOK ChecksumVerdict = "ok"
	// ChecksumMismatch: a stored B-checksum that the source does NOT reproduce — a
	// corrupted or tampered routine. This is the refuse signal.
	ChecksumMismatch ChecksumVerdict = "mismatch"
	// ChecksumNoStored: a "0"/empty stored checksum (a v-pkg build) — nothing to
	// verify; skipped, never false-failed.
	ChecksumNoStored ChecksumVerdict = "no-stored-checksum"
	// ChecksumUnknownFormat: a stored checksum in a form we cannot recompute (not "0"
	// and not "B<n>"). We cannot prove tamper, so we do not refuse — skipped + surfaced.
	ChecksumUnknownFormat ChecksumVerdict = "unknown-format"
)

type Component added in v0.6.0

type Component struct {
	File     float64
	FileStr  string
	DataRoot string
	Label    string
	Names    []string
}

Component is one entry-component TYPE a build ships, for the registry-driven generic presence-verify + uninstall-delete path: the file number, its KIDS render (the marker-key disambiguator), the authoritative storage global root (which yields BOTH the "B" presence index `<DataRoot>"B"` and the ^DIK delete ref `<DataRoot>`), the FileMan file name (human label), and the shipped .01 NAMEs in build order. One Component per registered type the build actually ships — the single place verify/uninstall learn "which records of which type by which name", so a new type becomes one registry row, not new per-type code.

type EntryContent added in v0.6.0

type EntryContent struct {
	File     float64
	FileStr  string
	Name     string
	DataRoot string
	Zero     string
	Volatile []int
}

EntryContent is what `v pkg verify` needs to assert a shipped KRN entry record is filed CORRECTLY, not merely present: the .01 NAME (the "B" lookup key), the data global it files into, the expected stored 0-node, and the 0-node ^-piece indices FileMan rewrites at install (skipped in comparison). FileStr is the file number rendered for the result marker key.

type FileContent added in v0.6.0

type FileContent struct {
	File    int64
	FileStr string
	Field   string
	Zero    string
}

FileContent is what a content-asserting `v pkg verify` needs per shipped FILE field: the file number, the field number (as a canonical M numeric string), and the expected ^DD(file,fld,0) definition node. FileMan files the DD verbatim (DDIN^DIFROMS moves the image in), so the live node matches Zero exactly — turning the FILE check from "the DD exists" into "the fields we shipped are defined as shipped."

type FileDD added in v0.2.0

type FileDD struct {
	Number     int64
	Name       string
	GlobalRoot string      // data global root, e.g. "^DIZ(999000,"
	Fields     []FileField // additional fields beyond the .01 NAME (empty = single-.01 file)
	Data       *FileData   // optional data records to ship with the file (nil = DD only)
}

FileDD is one brand-new FileMan FILE to ship as a data dictionary: its number, name, data global root (e.g. "^DIZ(999000,"), and zero or more fields beyond the implicit free-text .01 NAME. Only the DD is created — never data (the consumer files its own records through the FileMan DBS API).

type FileData added in v0.6.0

type FileData struct {
	Action  string // single send-options letter: a | m | o | r (validated upstream)
	Records []FileRecord
}

FileData is the set of records shipped with a file plus the install action that governs how they merge with any site data (FileMan field #9.64,222.8 SITE'S DATA, send-options piece 8): "a"=ADD ONLY IF NEW FILE, "m"=MERGE, "o"=OVERWRITE, "r"=REPLACE. The records ship under ("DATA",<file>,<ien>,<node>) — the raw record storage subtree DATAIN^DIFROMS (EN^DIFROMS4) loops and files via I^DITR.

type FileField added in v0.6.0

type FileField struct {
	Number   float64 // field number (> .01)
	Label    string  // field LABEL (^DD piece 1)
	Type     string  // one of the Field* constants
	Node     int     // storage node (the N in "N;piece")
	Piece    int     // storage piece (the P in "node;P")
	Required bool    // R attribute (RF / RS / RP… prefix)
	Help     string  // optional reader help → ,<field#>,3) node

	MaxLen int // free text: input-transform length cap

	Width    int      // numeric: NJ<width>,<decimals> print spec
	Decimals int      // numeric: decimal places (0 = integer)
	Min      *float64 // numeric: lower bound (nil = unbounded)
	Max      *float64 // numeric: upper bound (nil = unbounded)

	HasTime bool // date: allow a time component (%DT "ET" vs "E")

	Codes []SetCode // set of codes: the value list, in order

	PointTo   float64 // pointer: pointed-to file number → P<file>'
	PointRoot string  // pointer: pointed-to global root (^DD piece 3)
}

FileField is one FileMan field beyond the implicit .01 NAME, shipped in a brand-new file's DD. Node/Piece are the storage location ("<Node>;<Piece>", the ^DD definition node's piece 4); Type selects the piece-2 grammar and the input transform. The .01 is always a free-text NAME emitted separately; FileField covers fields numbered above it.

type FileRecord added in v0.6.0

type FileRecord struct {
	IEN   int64
	Nodes map[int]map[int]string
}

FileRecord is one data record to ship: its IEN and its storage nodes packed by node->piece->value (the .01 NAME is node 0 piece 1). The emitter caret-joins each node's pieces into the record's global node value, exactly as the live record would sit at <GlobalRoot><ien>,<node>).

type HL7App added in v0.6.0

type HL7App struct {
	Name        string // #771 .01 NAME (0;1)
	Facility    string // #771 field 3 FACILITY NAME (0;3)
	CountryCode string // #771 field 7 COUNTRY CODE (0;7) — e.g. "USA"
}

HL7App is one #771 HL7 APPLICATION PARAMETER record to ship as a KIDS KRN component (SEND-TO-SITE) — the canonical "register an HL7 application" entry. Stored in ^HL(771,. The record is a single 0-node: NAME ^ 2 ACTIVE/INACTIVE ^ 3 FACILITY NAME ^ ^ ^ ^ 7 COUNTRY CODE. The build pins ACTIVE = "a" (a shipped application registration is always active) and the country defaults to "USA"; the *HL7 SEGMENT/*HL7 MESSAGE legacy multiples are obsolete and never shipped. (The HLO registry #779.2 and logical link #870 — the other HL7-family files — are follow-ups; #870 carries site-specific network config and is not portably authorable.)

type HLOApp added in v0.6.0

type HLOApp struct {
	Name         string       // #779.2 .01 APPLICATION NAME (0;1)
	MessageTypes []HLOMsgType // #779.21 MESSAGE TYPE ACTIONS multiple
}

HLOApp is one #779.2 HLO APPLICATION REGISTRY record to ship as a KIDS KRN component — the HL7-Optimized (HLO) counterpart to #771: it registers an application and maps the HL7 message types it handles to action routines. Stored in ^HLD(779.2,. The record is the 0-node (APPLICATION NAME) plus the #779.21 MESSAGE TYPE ACTIONS multiple, each entry of which the emitter ships WITH its computed cross-references (the "B"/"C"/"D" indices KRN^XPDIK would otherwise rebuild) so the export is byte-identical to a native KIDS build.

type HLOMsgType added in v0.6.0

type HLOMsgType struct {
	MessageType   string // #779.21 .01 HL7 MESSAGE TYPE (0;1) — e.g. "ORU"
	Event         string // #779.21 .02 HL7 EVENT (0;2) — e.g. "R01"
	ActionTag     string // #779.21 .04 ACTION TAG (0;4)
	ActionRoutine string // #779.21 .05 ACTION ROUTINE (0;5)
	Version       string // #779.21 .06 HL7 VERSION (0;6) — e.g. "2.4"
}

HLOMsgType is one MESSAGE TYPE ACTIONS entry (#779.21 subfile) of an HLO application: which incoming HL7 message type/event the application handles and the action routine that processes it. MessageType (.01) and Event (.02) are free text and double as cross-reference keys; Version (.06) keys the "D" index when present.

type HelpFrame added in v0.6.0

type HelpFrame struct {
	Name   string   // #9.2 .01 NAME (0;1) — hyphen/space, 3–30 chars
	Header string   // #9.2 field 1 HEADER (0;2) — one-line summary
	Text   []string // #9.2 field 2 TEXT (WP, node 1) — the help body, in line order
}

HelpFrame is one #9.2 HELP FRAME record to ship as a KIDS KRN component (SEND-TO-SITE). Stored in ^DIC(9.2,. The record is the 0-node (.01 NAME ^ HEADER) plus the TEXT word-processing field (#9.2 field 2, subfile 9.21) at node 1 — the help content, which is the whole point of the type. The volatile DATE ENTERED (0;3) and DATE LAST UPDATED are OMITTED so the build stays deterministic, and the WP header is shipped date-less; the RELATED FRAME / INVOKED BY ROUTINE multiples are a follow-up.

type IENStats

type IENStats struct {
	BLD int `json:"BLD"`
	KRN int `json:"KRN"`
}

IENStats reports how many IEN substitutions CanonicalizeIENs made per section.

func CanonicalizeIENs

func CanonicalizeIENs(decompDir string) (IENStats, error)

CanonicalizeIENs rewrites every .zwr under decompDir to substitute integer IENs at known positions with the literal "IEN" — for cross-instance diffing. LOSSY: the original IENs are discarded (KIDS reassigns them on install). Port of canonicalize_iens.

  • ("BLD", <int>, …) → position 1 (build IEN)
  • ("KRN", <numeric>, <int≠0>…) → position 2 (entry IEN per file)

func (IENStats) Total

func (s IENStats) Total() int

Total is the sum of all substitutions.

type KID

type KID struct {
	InstallNames []string
	Builds       map[string]*Build
}

KID is a parsed KIDS distribution: the ordered install names plus each install's build data.

func ParseKID

func ParseKID(path string) (*KID, error)

ParseKID parses a .KID file. It is the port of py-kids-vc's parse_kid state machine: BEGIN → KIDSSS → INSTLNM → CONTENT, looping back to INSTLNM on each new install and pairing subscript lines with their following value line.

type LintFinding

type LintFinding struct {
	File     string    `json:"file"`     // file number as it appears
	Class    PIKSClass `json:"class"`    // resolved PIKS class
	Section  string    `json:"section"`  // KIDS data section it appeared in
	Severity string    `json:"severity"` // "error" (blocked) | "warning" (unclassified)
	Message  string    `json:"message"`
}

LintFinding is one data-class gate finding against a single FileMan file.

type LintResult

type LintResult struct {
	Findings     []LintFinding `json:"findings"`
	DataFiles    int           `json:"dataFiles"`    // distinct files with operational data
	Blocked      int           `json:"blocked"`      // Patient/Institution findings
	Unclassified int           `json:"unclassified"` // files with no known class
	OK           bool          `json:"ok"`           // gate passed
}

LintResult is the outcome of the data-class gate.

func LintDataClass

func LintDataClass(kid *KID, classifier *PIKSClassifier, strict bool) LintResult

LintDataClass runs the PIKS data-class gate (K2 / N9) over a parsed KID. Operational-data (DATA/FRV*) sections touching a Patient/Institution-class file are gate FAILURES (severity error). Files with no known class are reported as warnings; with strict=true they are also treated as gate failures (fail-closed when no authoritative classifier is supplied).

type ListTemplate added in v0.6.0

type ListTemplate struct {
	Name         string // #409.61 .01 NAME (0;1)
	ScreenTitle  string // .11 SCREEN TITLE (0;11)
	ProtocolMenu string // .1 PROTOCOL MENU (0;10) — #101 action-menu pointer by name
	RightMargin  string // .04 RIGHT MARGIN (0;4)
	TopMargin    string // .05 TOP MARGIN (0;5)
	BottomMargin string // .06 BOTTOM MARGIN (0;6)
	HeaderCode   string // field 100 HEADER CODE — node "HDR" (M code)
	EntryCode    string // field 106 ENTRY CODE — node "INIT" (M code)
	ExitCode     string // field 105 EXIT CODE — node "FNL" (M code)
	HelpCode     string // field 103 HELP CODE — node "HLP" (M code)
	ArrayName    string // field 107 ARRAY NAME — node "ARRAY" (the display global ref)
}

ListTemplate is one #409.61 LIST TEMPLATE (List Manager screen) record to ship as a KIDS KRN component (SEND-TO-SITE). Stored in ^SD(409.61,. The record is a fixed 14-piece 0-node (screen geometry + a PROTOCOL MENU pointer + the title) plus the List Manager callback nodes (HDR/INIT/FNL/HLP M code + the ARRAY global). Unlike the FileMan TEMPLATE family (#.4/.402/…), a list template carries NO compiled structure — every node is a plain string — so it authors cleanly from a spec. Margins/codes are pre-resolved strings (build.go applies the geometry defaults).

type LogicalLink struct {
	Name        string   // #870 .01 NODE (0;1) — 3..10 chars, no leading punctuation
	LLPType     string   // #870 field 2 LLP TYPE (0;3) — #869.1 pointer, external e.g. "TCP"
	Port        string   // #870 400.02 TCP/IP PORT (400;2)
	ServiceType string   // #870 400.03 TCP/IP SERVICE TYPE (400;3) — C/S/M
	Description []string // #870 field 1 DESCRIPTION (subfile 870.02 at node 3), optional
}

LogicalLink is one #870 HL LOGICAL LINK record to ship as a KIDS KRN component — an HL7 communication endpoint. Stored in ^HLCS(870,. The record is the sparse 0-node (NODE name ^ ^ LLP TYPE) plus, when a TCP param is set, the 400-node (^ PORT ^ SERVICE TYPE). LLP TYPE ships as the external #869.1 value ("TCP") and KIDS resolves it to the live IEN at install (the same external-pointer mechanism #771's COUNTRY CODE uses).

Deliberately NO DNS DOMAIN / TCP/IP ADDRESS: the #870 install routine (HLLL/ HLLLE^XPDIA1) re-files the record through FileMan, and those two fields are site-specific network config that the install does NOT carry — DNS DOMAIN's input transform DNS-resolves the host ($$ADDRESS^XLFNSLK) and drops itself (plus the coupled TCP/IP ADDRESS) when it can't, and a bare TCP/IP ADDRESS is dropped outright (live-proven on vehu). v-pkg ships only what actually lands — the link definition (name, protocol, port, role); the receiving site configures the endpoint. (The DESCRIPTION word-processing field #870.02 is a follow-up.)

type MailGroup added in v0.6.0

type MailGroup struct {
	Name            string   // #3.8 .01 NAME (0;1)
	TypeCode        string   // #3.8 field 4 TYPE set-of-codes value (0;2): PU / PR
	AllowSelfEnroll string   // #3.8 field 7 ALLOW SELF ENROLLMENT (0;3): y / n / ""
	Description     []string // #3.8 field 3 DESCRIPTION (subfile 3.801 at node 2), optional
}

MailGroup is one #3.8 MAIL GROUP record to ship as a KIDS KRN component (SEND-TO-SITE). Stored in ^XMB(3.8,; the record is a single 0-node NAME^TYPE^ALLOW-SELF-ENROLLMENT. TypeCode is the #3.8 field 4 (TYPE) set-of-codes value (PU public / PR private) — a DD-REQUIRED field, so it always ships. AllowSelfEnroll is field 7 (y/n), optional. KIDS ships mail groups MEMBER-less (the #3.81 MEMBER multiple points to site-local #200 entries, added on site); the word-processing DESCRIPTION (field 3, node 2) is deferred — its header carries a volatile last-edited date that would defeat the deterministic-build invariant.

type Option added in v0.6.0

type Option struct {
	Name        string           // #19 .01 NAME (0;1)
	MenuText    string           // #19 field 1 MENU TEXT (0;2)
	TypeCode    string           // #19 field 4 TYPE set-of-codes value
	Routine     string           // #19 field 25 ROUTINE entryref (run-routine type); node 25
	EntryAction string           // #19 field 20 ENTRY ACTION (M code); node 20
	ExitAction  string           // #19 field 15 EXIT ACTION (M code); node 15
	MenuItems   []OptionMenuItem // #19.01 MENU multiple (node 10), optional — menu children
}

Option is one #19 OPTION record to ship as a KIDS KRN component (SEND-TO-SITE). The build files the option definition; TypeCode is the #19 field 4 (TYPE) set-of-codes value (e.g. "R" run routine, "A" action). Storage (ground-truthed against the live #19 DD): MENU TEXT 0;2, TYPE 0;4, EXIT ACTION node 15, ENTRY ACTION node 20, ROUTINE node 25, UPPERCASE MENU TEXT node "U".

type OptionMenuItem added in v0.6.0

type OptionMenuItem struct {
	Name         string // child OPTION .01 NAME (the #19 pointer target)
	Synonym      string // #19.01 field 2 SYNONYM (0;2)
	DisplayOrder string // #19.01 field 3 DISPLAY ORDER (0;3)
}

OptionMenuItem is one MENU entry (#19.01 subfile) of a menu option: the child OPTION it points to, its synonym, and its display order. The .01 ITEM is a #19 pointer transported via the KIDS "^" resolver convention (placeholder IEN + "^" NAME node), same as PROTOCOL #101.01 — see entrycomp ProtocolItem.

type PIKSClass

type PIKSClass string

PIKSClass is the data-sensitivity class of a FileMan file under vista-meta's PIKS model: Patient, Institution, Knowledge, or System. Patient/Institution are operational data (refused from the versioned tree); Knowledge/System are definitional configuration (safely packageable). See kids-package-round-trip §3 and ADR-045 (data/code separation).

const (
	ClassPatient     PIKSClass = "Patient"
	ClassInstitution PIKSClass = "Institution"
	ClassKnowledge   PIKSClass = "Knowledge"
	ClassSystem      PIKSClass = "System"
	ClassUnknown     PIKSClass = "Unknown"
)

type PIKSClassifier

type PIKSClassifier struct {
	// contains filtered or unexported fields
}

PIKSClassifier classifies FileMan file numbers. It layers an external table (authoritative, from vista-meta) over the built-in seed.

func NewPIKSClassifier

func NewPIKSClassifier() *PIKSClassifier

NewPIKSClassifier returns a classifier seeded with the built-in map.

func (*PIKSClassifier) Classify

func (c *PIKSClassifier) Classify(fnum float64) PIKSClass

Classify returns the class of a file number (Unknown if unseen).

func (*PIKSClassifier) LoadPIKS

func (c *PIKSClassifier) LoadPIKS(path string) error

LoadPIKS overlays an external PIKS table onto the classifier. The file is a TSV (or whitespace-separated) of `filenumber<sep>class` lines; `class` may be a single letter (P/I/K/S) or a full word (Patient/…). Blank lines and lines beginning with '#' are ignored. This is how vista-meta's authoritative PIKS export is supplied — v pkg never vendors it.

type Pair

type Pair struct {
	Subs  Subs
	Value string
}

Pair is one (subscript, value) entry of a build.

func AssembleBuild

func AssembleBuild(inDir, installName string) ([]Pair, error)

AssembleBuild reads a decomposed component tree under inDir and reconstructs the (subscript, value) pairs of one build. Port of assemble_build; installName is accepted for parity but unused (no IEN substitution in the MVP contract).

func CanonicalPairs

func CanonicalPairs(build *Build) []Pair

CanonicalPairs returns a build's pairs sorted by the _sort_key collation, with routine line-2 values canonicalized — the form round-trip equality is checked against. Port of _canonical_pairs.

func EnginePairs added in v0.6.0

func EnginePairs(pairs []Pair) []Pair

EnginePairs returns the transport pairs that may be staged to a live engine — every pair EXCEPT v-pkg's private metadata nodes (the ("VPKG",…) foreign- overwrite declaration). The install path filters through this so the .KID can carry a declaration v-pkg reads offline without ever shipping a non-KIDS node into the engine's transport global / KIDS filing.

func MakeBuildPairs

func MakeBuildPairs(in BuildInput) []Pair

MakeBuildPairs constructs the ^XPD BUILD pairs for a routine-only KIDS package (BLD header + RTN sections + VER), with volatile fields NORMALIZED — the build date is 0 and routine checksums are stripped to 0 — so the same input yields a byte-identical export. This is the minimal correct shape for a routine package (the ZZSKEL throwaway); richer components (files/options/KRN/Required Builds) are added as the live install path (T0a.3+) validates them against real KIDS.

func StampHash added in v0.6.0

func StampHash(pairs []Pair) []Pair

StampHash returns pairs with a ("VPKG","HASH") node appended carrying HashPairs of the input. Because HashPairs excludes ("VPKG",…) nodes, re-stamping or re-hashing a stamped build yields the same value. Called at snapshot capture so the same capture always stamps the same hash.

type ParamDef added in v0.2.0

type ParamDef struct {
	Name         string
	DisplayText  string
	DataTypeCode string // #8989.51 1.1 set-of-codes value; "" → "F" (free text)
	Entities     []ParamEntity
}

ParamDef is one #8989.51 record to ship: NAME + DISPLAY TEXT, the value data type code (#8989.51 field 1.1, e.g. "F" for free text), and the ALLOWABLE ENTITIES rows. The build creates the definition only — never a value.

type ParamEntity added in v0.2.0

type ParamEntity struct {
	EntityIEN  string // #8989.518 IEN (DINUM to file #, e.g. "4.2" = SYS)
	Precedence int    // #8989.513 .01 PRECEDENCE; 0 → 1
}

ParamEntity is one ALLOWABLE ENTITIES row: the #8989.518 entity IEN the parameter may be set at, and its precedence.

type Protocol added in v0.6.0

type Protocol struct {
	Name        string         // #101 .01 NAME (0;1)
	ItemText    string         // #101 field 1 ITEM TEXT (0;2)
	TypeCode    string         // #101 field 4 TYPE set-of-codes value
	EntryAction string         // #101 field 20 ENTRY ACTION (M code); node 20
	ExitAction  string         // #101 field 15 EXIT ACTION (M code); node 15
	Items       []ProtocolItem // #101.01 ITEM multiple (node 10), optional — menu children
}

Protocol is one #101 PROTOCOL record to ship as a KIDS KRN component (SEND-TO-SITE). Stored in ^ORD(101,; the node skeleton matches OPTION but the TYPE codes and data global are #101's own, and there is no uppercase-text xref. TypeCode is the #101 field 4 (TYPE) set-of-codes value (A action, X extended action, M menu, E event driver, …). The #101.01 ITEM multiple (menu items) and the extended menu-actions are a follow-up — this authors a base protocol.

type ProtocolItem added in v0.6.0

type ProtocolItem struct {
	Name     string // child PROTOCOL .01 NAME (the #101 pointer target)
	Sequence string // #101.01 field 3 SEQUENCE (0;3)
}

ProtocolItem is one ITEM (#101.01 subfile) of a menu protocol: the name of the child PROTOCOL it points to, and the child's display sequence. The .01 ITEM is a #101 pointer; KIDS transports it as the source IEN in the data node PLUS a "^" resolver node carrying the child's NAME, which the install re-points at the target site.

type RPC added in v0.6.0

type RPC struct {
	Name           string     // #8994 .01 NAME (0;1)
	Tag            string     // #8994 .02 TAG — the M entry tag (0;2)
	Routine        string     // #8994 .03 ROUTINE — the M routine (0;3)
	ReturnTypeCode string     // #8994 .04 RETURN VALUE TYPE set-of-codes value (0;4)
	InputParams    []RPCParam // #8994.02 INPUT PARAMETER multiple (node 2), optional
}

RPC is one #8994 REMOTE PROCEDURE record to ship as a KIDS KRN component (SEND-TO-SITE). Stored in ^XWB(8994,; the record is a single 0-node carrying the three DD-required fields (NAME/.01, ROUTINE/.03, RETURN VALUE TYPE/.04) plus TAG (.02, functionally required for the RPC to run). ReturnTypeCode is the #8994 field .04 set-of-codes value (1 single value, 2 array, 3 word processing, …).

type RPCParam added in v0.6.0

type RPCParam struct {
	Name        string   // #8994.02 .01 INPUT PARAMETER (0;1)
	TypeCode    string   // #8994.02 .02 PARAMETER TYPE set value (0;2): 1 literal/2 list/3 WP/4 reference
	MaxLength   string   // #8994.02 .03 MAXIMUM DATA LENGTH (0;3)
	RequiredVal string   // #8994.02 .04 REQUIRED set value (0;4): 1 yes/0 no
	Sequence    string   // #8994.02 .05 SEQUENCE NUMBER (0;5)
	Description []string // #8994.02 field 1 DESCRIPTION (subfile 8994.021), optional
}

RPCParam is one INPUT PARAMETER (#8994.02 subfile) of an RPC: its name, type, max length, required flag, sequence, and an optional DESCRIPTION word-processing field (subfile 8994.021).

type ReqBuild added in v0.2.0

type ReqBuild struct {
	Name   string
	Action int
}

ReqBuild is one Required Build (#9.611): the prerequisite build name and the action KIDS takes when it is absent (0 warn, 1 remove global, 2 leave global).

type Reversibility added in v0.2.0

type Reversibility struct {
	Class     ReversibilityClass   `json:"class"`
	ClassName string               `json:"className"`
	Builds    []BuildReversibility `json:"builds"`
}

Reversibility is the whole-distribution analysis: per-build plus the overall class, where the LEAST-reversible build governs (a multi-build patch is only as reversible as its most side-effecting member).

func Classify added in v0.2.0

func Classify(k *KID) Reversibility

Classify derives reversibility for every build in a KID. The overall class is the least-reversible build (SideEffecting if ANY build is side-effecting).

type ReversibilityClass added in v0.2.0

type ReversibilityClass int

ReversibilityClass is the statically-derived reversibility of a KIDS build — the keystone the proposal (docs/patch-existing-routines-proposal.md) requires: "detect the class from the .KID, don't trust the tag." It is derived ONLY from the transport global's structure, with no live engine.

Corpus evidence (docs/kids-corpus-findings.md, 2,404 WorldVistA distributions): the pure-overwrite class is the MINORITY (~35%); ~64% are side-effecting. So the safe default for anything carrying install code, FileMan entries, or DD/data is SideEffecting — snapshot/restore is sound ONLY for PureOverwrite.

const (
	// ClassPureOverwrite (class 1): ships only routine/metadata overwrites — no
	// install-time code, no exported FileMan entries, no DD/data. A pre-image
	// snapshot+restore fully reverses it. This is the XWBBRK-splice class.
	ClassPureOverwrite ReversibilityClass = iota + 1
	// ClassSideEffecting (class 2/3): runs install-time code (env-check /
	// pre-install / post-install) and/or files FileMan entries and/or ships
	// DD/data. There is no generic inverse — reversal needs an authored back-out
	// (class 2) or a forward back-out patch (class 3); restoring a routine
	// pre-image is incomplete and unsafe.
	ClassSideEffecting
)

func (ReversibilityClass) String added in v0.2.0

func (c ReversibilityClass) String() string

type RoundtripDiff

type RoundtripDiff struct {
	Build  string `json:"build"`
	PairsA int    `json:"pairsA"`
	PairsB int    `json:"pairsB"`
	FirstA string `json:"firstA,omitempty"`
	FirstB string `json:"firstB,omitempty"`
}

RoundtripDiff is the first divergence found in a build that failed to round-trip.

type RoundtripResult

type RoundtripResult struct {
	File   string `json:"file"`
	Builds int    `json:"builds"`
	Pairs  int    `json:"pairs"`
	OK     bool   `json:"ok"`
	// Diff is populated on failure: the first divergence per mismatched build.
	Diff []RoundtripDiff `json:"diff,omitempty"`
}

RoundtripResult summarizes a round-trip verification.

func Roundtrip

func Roundtrip(kidPath string) (RoundtripResult, error)

Roundtrip parses, decomposes, reassembles, and re-parses kidPath, then verifies canonical equality. It is the oracle for the G6 gate. Port of roundtrip; the guarantee is semantic equality after line-2 canonicalization, not byte-identity.

type RoutineSrc

type RoutineSrc struct {
	Name  string
	Lines []string
}

RoutineSrc is one routine's name and source lines.

type SecurityKey added in v0.6.0

type SecurityKey struct {
	Name        string   // #19.1 .01 NAME (0;1)
	Description []string // #19.1 field 1 DESCRIPTION (subfile 19.11 at node 1), optional
}

SecurityKey is one #19.1 SECURITY KEY record to ship as a KIDS KRN component (SEND-TO-SITE). A key is fundamentally just a named token holders are granted; the record image is minimal — the .01 NAME alone (stored in ^DIC(19.1,). The optional DESCRIPTION (word-processing) field is a follow-up.

type SetCode added in v0.6.0

type SetCode struct {
	Internal string
	External string
}

SetCode is one internal:external pair of a set-of-codes field (^DD piece 3 is the ";"-terminated list of these).

type Sub

type Sub struct {
	// contains filtered or unexported fields
}

Sub is one subscript element: a quoted string, an integer, or a decimal file number. Numerics keep their parsed value (for sorting, equality keys, and the int/float/zero tests the decomposer makes); on output they are reformatted from the value the way Python's str() renders them — `.4` normalizes to `0.4`, matching py-kids-vc byte-for-byte. String elements are quoted/escaped.

func (Sub) Int

func (s Sub) Int() int64

Int returns the integer value (0 for non-ints).

func (Sub) IsFloat

func (s Sub) IsFloat() bool

IsFloat reports whether the element is a decimal (file-number) subscript.

func (Sub) IsInt

func (s Sub) IsInt() bool

IsInt reports whether the element is an integer subscript.

func (Sub) IsNumeric

func (s Sub) IsNumeric() bool

IsNumeric reports whether the element is an int or float subscript.

func (Sub) IsStr

func (s Sub) IsStr() bool

IsStr reports whether the element is a string subscript.

func (Sub) IsZeroInt

func (s Sub) IsZeroInt() bool

IsZeroInt reports whether the element is the integer 0 — the IEN=0 file-header marker the KRN decomposer keys on.

func (Sub) Str

func (s Sub) Str() string

Str returns the string value (empty for numerics).

type Subs

type Subs []Sub

Subs is a parsed subscript tuple — the tail of a $NA reference such as `"KRN",19,12345,0)`.

func (Subs) MRef

func (s Subs) MRef(rootOpen string) string

MRef returns the M global reference for this subscript tail, opened by rootOpen. rootOpen must end at an open paren plus any fixed leading subscripts — e.g. `^XTMP("XPDI",XPDA,` — and MRef supplies the closing paren. So Subs{"RTN","ZZSKEL",5,0}.MRef(`^XTMP("XPDI",XPDA,`) yields `^XTMP("XPDI",XPDA,"RTN","ZZSKEL",5,0)`.

func (Subs) Section

func (s Subs) Section() string

Section returns the top-level KIDS section name (the leading string element), or "UNKNOWN" when the tuple is empty or doesn't begin with a string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL