buildRuntimeInputs reads each policy input file and returns the extracted values grouped for the policy engine: unscoped entries under Global and policy-scoped entries under Scoped[policy]. Values are newline-joined and accumulated via policies.MergeRuntimeInputs so repeated inputs merge using the s
(policyInputFiles []*PolicyInputFromFile)
| 197 | // newlines and commas). As with contract-declared arguments, individual values |
| 198 | // must not embed those delimiters; path globs, the intended use, never do. |
| 199 | func buildRuntimeInputs(policyInputFiles []*PolicyInputFromFile) (*policies.RuntimeInputs, error) { |
| 200 | if len(policyInputFiles) == 0 { |
| 201 | return nil, nil |
| 202 | } |
| 203 | |
| 204 | ri := &policies.RuntimeInputs{ |
| 205 | Global: map[string]string{}, |
| 206 | Scoped: map[string]map[string]string{}, |
| 207 | } |
| 208 | for _, pif := range policyInputFiles { |
| 209 | values, err := ExtractColumnValues(pif.File, pif.Column) |
| 210 | if err != nil { |
| 211 | return nil, fmt.Errorf("extracting %q from %q: %w", pif.Column, pif.File, err) |
| 212 | } |
| 213 | |
| 214 | // Unscoped entries go to Global; policy-scoped entries to their own |
| 215 | // Scoped[policy] map. Because global and scoped values live in separate |
| 216 | // maps, they never collide here even when they share an input name; |
| 217 | // forPolicy is what later merges a policy's scoped values over Global. |
| 218 | add := map[string]string{pif.Input: strings.Join(values, "\n")} |
| 219 | if pif.Policy == "" { |
| 220 | ri.Global = policies.MergeRuntimeInputs(ri.Global, add) |
| 221 | } else { |
| 222 | ri.Scoped[pif.Policy] = policies.MergeRuntimeInputs(ri.Scoped[pif.Policy], add) |
| 223 | } |
| 224 | } |
| 225 | |
| 226 | return ri, nil |
| 227 | } |
| 228 | |
| 229 | // addPolicyInputEvidence adds each policy input file as an EVIDENCE material, |
| 230 | // cross-linked with the evaluated material in both directions via the |