@meada/meada 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,710 @@ All notable changes to Meada are recorded here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.3.0] - 2026-11-11
10
+
11
+ A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
12
+ infrastructure joins the graph. Config values and IaC nodes (ADR 0025) are read from Terraform and
13
+ OpenTofu (HCL and JSON, with static evaluation of names), Compose, CloudFormation and SAM,
14
+ Serverless Framework, Kubernetes with Kustomize, and Crossplane, and answer to the new `search`
15
+ kinds `value` and `iac` (`image` and `alert` join for their contracts). Infrastructure contracts (ADR 0026) link the code that uses a queue, a
16
+ topic, a bucket, a table, a parameter or a secret to what provisions it on AWS, GCP and Azure,
17
+ through SDK use sides in TypeScript, JavaScript, Python, Java, Go and C#, with orphan reports in
18
+ `meada status`. Image contracts link builders to runners, workloads carry their environments to the
19
+ code they run, alert contracts link rule labels to Alertmanager routes and Datadog
20
+ monitor tags to OpsGenie routing, and HTTP gains route
21
+ providers declared in IaC and base URLs followed through Kubernetes Services, Ingresses and Compose.
22
+ The console graph shows the new roles, a refresh reads unchanged values from a cache beside the
23
+ index (`values.db`, ADR 0027), and `meada mcp` answers calls sent without waiting for each reply
24
+ (#704). The index schema changes, so existing indexes are rebuilt once on first use; export format
25
+ stays 1 and gains optional fields. `meada-core` 1.3.0 gives `ids::VersionEntry` a sixth element and
26
+ `ids::NON_BLOCK_KEYS` a fifth key (`added_by_time`, #454), `authorize::compose_entries` a `now`
27
+ parameter, `manifest::EntryFile` an `added_by_time` field and the export structs new fields.
28
+ Postgres migration 10 needs `meada postgres migrate` before 1.3.0 starts, and 1.2.0 binaries
29
+ refuse the migrated schema. The
30
+ entries below that name a release level were written while this release was in development. The
31
+ tree, the `meada-core` pin, the Dockerfile, the compose defaults and the Helm chart declare `1.3.0`,
32
+ and the `v1.3.0` tag goes on the `release/1.3` branch, cut from this entry's merge on main.
33
+ Publication (crates, the staged npm package, the GitHub draft release) belongs to the maintainer.
34
+ Release notes are available in
35
+ [pt-BR](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.3.0.md),
36
+ [English](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.3.0.en.md) and
37
+ [Spanish](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.3.0.es.md).
38
+
39
+ ### Added
40
+
41
+ - DynamoDB transactions in Java, Go and C# (#719): `TransactWriteItems` and `TransactGetItems`
42
+ give sides as they do in JavaScript and Python. Each `Put`, `Update` and `Delete` entry
43
+ writes its own table, each `ConditionCheck` and `Get` entry reads its own, with the literal
44
+ and environment rules of the other names. A list or an array of entries held in a name (in
45
+ Go and C#, a request, an item or an entry too) gives its tables only when its function
46
+ mentions the name twice, where it is declared and where the request reads it: any other
47
+ mention may change it, and one that comes in a parameter (in Java, a single entry too) gives
48
+ none. Every Java, Go and .NET AWS operation now has a test. Included in the 1.3.0 minor
49
+ release.
50
+ - Curated operators and private IaC mappings (#671): 43 explicit Strimzi, RabbitMQ Queue,
51
+ ACK, Config Connector and Crossplane AWS/GCP/Azure types provision existing contracts.
52
+ RabbitMQ Exchange/Binding topology routes real publishes to queues without inventing an
53
+ exchange channel. Six terraform-aws-modules sources read declared resource and Lambda/ECS
54
+ workload inputs; `meada.toml` maps exact/private source prefixes and custom group/kind key
55
+ paths to curated entries. Unknown identities and creation controls remain conservative.
56
+ This joins the existing 1.3.0 minor development release.
57
+ - IaC HTTP route providers (#666): Terraform/OpenTofu API Gateway HTTP/REST and explicit quick
58
+ create, SAM Api/HttpApi and Serverless http/httpApi events resolve to local handler symbols
59
+ or the repository, with normalized parameters, cross-repository HTTP links and stored
60
+ path/target evidence. Included in the meada/meada-core 1.3.0 minor release.
61
+ - Azure SDK sides in JavaScript/TypeScript, Python, Java, Go and C# (#670): verified
62
+ constructors connect Service Bus and Event Hubs sends/receives, Blob container reads/writes
63
+ and Key Vault secret reads to physical contracts. New subscription receivers retain their
64
+ topic and subscription through exact factories and scoped workload environments. Existing
65
+ C# Service Bus forms keep their identities; resource readers retain each operation site.
66
+ The bounded inventory joins the shared meada/meada-core 1.3.0 minor release.
67
+
68
+ - GCP SDK use sides in JavaScript/TypeScript, Python, Java, Go and C# (#668): verified client
69
+ constructors connect Pub/Sub publish and subscription receive, Cloud Storage reads/writes
70
+ and Secret Manager access to their physical contracts. Subscription identities remain
71
+ distinct from topics through scoped workload environment resolution. The documented
72
+ operation inventory ships in the shared meada 1.3.0 minor release. Scoped request mutations
73
+ leave stale names unresolved, typed helpers retain their resource kind through factories,
74
+ and asynchronous factories preserve await state.
75
+ - The console graph has image builder-to-runner and alert emitter-to-matcher views, including
76
+ links within a repository, alongside provisioner sides and provisioning links with roots,
77
+ levels and reasons. A bilingual legend explains each role and keyboard navigation. The
78
+ playground exposes `value`, `iac` and `alert` searches. Release level: minor, included in
79
+ meada and meada-core 1.3.0 (#675).
80
+ - Datadog Terraform monitor tags join OpsGenie routing conditions through known tag
81
+ forwarding. Selected Alertmanager receivers explicitly transform grouped rule labels
82
+ into OpsGenie tags or PagerDuty v2 custom details; native PagerDuty PCL conditions keep
83
+ their field paths. Equality is exact; regex, prefix and containment are inferred.
84
+ Missing or unread forwarding yields no link, and matching never predicts final team
85
+ delivery. Included in the existing meada/meada-core 1.3.0 minor release (#673).
86
+ - AWS workload execution and environments (#664): Terraform/OpenTofu Lambda images and local
87
+ code/archive inputs, SAM CodeUri/Handler/ImageUri with Globals overrides, Serverless handlers
88
+ with provider/function environments, and encoded ECS container images/environments. Known
89
+ resource references retain typed identities; secret and dynamic contents remain unread.
90
+ Context, bidirectional traces and scope-aware image orphans include these workloads; new
91
+ local paths refuse absolute paths, every parent component and symbolic links. Included in
92
+ the minor development release of meada and meada-core 1.3.0.
93
+
94
+ - Terraform/OpenTofu JSON (`.tf.json`, `.tofu.json`) now creates IaC nodes with source spans,
95
+ references, evaluated names and local module instances. JSON expression and literal rules
96
+ share the HCL evaluator, provisioners and subscriptions; declared resource `via` addresses
97
+ resolve to JSON nodes and refresh when sources change. Sensitive defaults, tfvars and SSM
98
+ SecureString values also stay redacted in JSON block arrays, a root array of bodies included,
99
+ and a JSON `dynamic` property merges as the types it names (#642, #649).
100
+ - Azure Terraform/OpenTofu contracts (#669): Service Bus queues, topics and topic-qualified
101
+ subscriptions with filter routing, Event Hubs, Storage accounts and blob containers as
102
+ distinct kinds, and Key Vault secrets. ARM identifiers and supported blob/vault URLs give
103
+ exact config uses; provider-specific typed keys remain inferred. Linux Functions run
104
+ evaluated container images; Linux and Windows Functions run safe local deployment archives, with scoped
105
+ app settings and unresolved Key Vault references. Existing C# topic processors retain
106
+ their topic identity. This shares the 1.3.0 development release.
107
+
108
+ - HTTP base URLs follow Kubernetes Service DNS names and Compose service names through their
109
+ workloads to the repositories running the providers. Ingress hosts and literal prefixes
110
+ carry public URLs to their Services; rewrites remain unread mounts. Links are inferred and
111
+ name the Service, with workload environment provenance when applicable. A Service or
112
+ Ingress that reaches no code leaves a host to `[serve] hosts`, which still links it `exact`.
113
+ Included in the minor development release of meada and meada-core 1.3.0 (#665).
114
+ - GCP infrastructure contracts (#667): Terraform/OpenTofu Pub/Sub topics and distinct
115
+ subscription targets, Cloud Storage buckets, Cloud SQL instances and instance-qualified
116
+ databases, and Secret Manager secrets. Structured GCP configuration identifiers are exact;
117
+ provider-specific typed keys remain inferred. Cloud Run v1/v2 services and v2 jobs retain
118
+ container images and scoped environment targets. Provisioning, subscriptions, context,
119
+ trace, scope-aware orphans and export include these kinds and runners. Release level: minor,
120
+ included in meada and meada-core 1.3.0.
121
+ - Declared resource `via` locations now accept IaC addresses in every indexed format and
122
+ `<file>#<key path>` with list selectors (`[key=value]`). Sides retain their precise node or
123
+ key for context and trace; removed locations produce the existing stale status diagnostics.
124
+ Release level: minor, included in meada and meada-core 1.3.0 (#641).
125
+ - Resolve environment reads through the workloads running their code, including Kubernetes ConfigMap references and Compose defaults, with inferred provenance and redacted Secret targets (#663).
126
+ - Alert contracts join Prometheus, Loki, PrometheusRule and Grafana rule labels to Alertmanager
127
+ route matchers, including AlertmanagerConfig. Equality is exact and regular expressions are
128
+ inferred; a negated condition only filters its route, without linking the value it refuses.
129
+ Route context includes the receiver, trace walks both ways, and export and scope-aware
130
+ orphan reports carry the kind. Helm values are not alert emitters. Included in the minor
131
+ development release of meada and meada-core 1.3.0 (#672).
132
+ - Anchored unresolved names across channel, resource and image contracts (#674): only
133
+ literal counterparts with sufficient anchor evidence and whole-segment wildcards link.
134
+ Several names remain ambiguous open items; human or optional decider choices replay through
135
+ `meada.decisions.toml`, including provisioning links and stale-choice reporting. Release
136
+ level: minor, included in meada and meada-core 1.3.0.
137
+
138
+ - Constructor-backed AWS SDK sides in Java 2.x, Go v2 and .NET: SQS, SNS, EventBridge, Kinesis,
139
+ S3, DynamoDB, SSM Parameter Store and Secrets Manager. Literal names and ARNs join
140
+ infrastructure contracts; environment reads retain their variable without a guessed name.
141
+ Every batch name is kept. Exact factories and aliases are followed, hidden bindings and
142
+ incomplete origins are rejected, and injected types alone create no SDK side, except SQS,
143
+ whose declared client types keep its earlier forms. .NET named requests and its S3 metadata
144
+ spelling are supported. SDK resource links are exact while declarations remain declared;
145
+ hierarchy queries stay unresolved. Release level: minor, meada and meada-core 1.3.0 (#660).
146
+ - AWS SDK use sides in TypeScript, JavaScript (SDK v3) and Python (boto3): SNS publishes,
147
+ EventBridge event entries and Kinesis record writes produce channel sides; S3 and DynamoDB
148
+ operations write or read resource sides; SSM and Secrets Manager operations read resources. Batch
149
+ and transaction inputs retain each named resource. Both client and operation origins must be the
150
+ SDK's; name-matched hops and hidden client names produce no side. Complete Python factory evidence
151
+ rejects opaque or missing returns and unawaited coroutine or generator objects, preserves exact
152
+ arguments, class fields and awaited aliases, and shares bounded constructor traversal with
153
+ existing message clients (#659).
154
+ - AWS SDK use sides: literal names and supported ARNs join provisioners at `exact`; environment
155
+ reads stay unresolved and name their variable through `via: env:NAME`, without reading the process
156
+ environment. SDK providers gain an optional `via`, absent on existing providers; format remains 1.
157
+ Existing declared resource sides retain `declared`. Older indexes rebuild. Release level: minor,
158
+ meada and meada-core 1.3.0 (#659).
159
+ - Config values naming AWS resources become directionless use sides (#661): recognized ARNs,
160
+ SQS queue URLs and S3 URIs are exact; plain names under final `queue`, `topic`, `bucket` and
161
+ `table` keys are inferred. Each key links only to provisioners and counts for scoped orphans;
162
+ bare equal values, redacted/cut values and provisioner name definitions create no use.
163
+ Search, context, trace, export's optional `uses` and the console retain key locations
164
+ without adding producer/consumer or writer/reader links. Release level: minor, meada and
165
+ meada-core 1.3.0.
166
+ - Image contracts (#662): normalized `image::<registry>/<repository>` names connect builders
167
+ in GitHub Actions, Compose, Skaffold, ko and Jib to Kubernetes, Compose and Helm runners,
168
+ including Kustomize image overrides. Context shows builders, trace crosses into code and
169
+ back, and status reports image orphans only in scopes with both roles. A Compose build runs
170
+ same-repository code directly at `exact`, without following symlinks: the paths its Dockerfile
171
+ takes from the context (`COPY`, `ADD` and `RUN` bind mounts, in every stage), not the whole of
172
+ it, and `inferred` when it cannot read one; editing the Dockerfile makes the index stale and an
173
+ upward `trace` writes each workload once (#744). Export format 1 adds optional builder `at`
174
+ locations and direct `executions`; the console graph displays both. Release level: minor for
175
+ meada and meada-core, included in synchronized 1.3.0.
176
+
177
+ - AWS infrastructure contracts: Terraform/OpenTofu SNS, EventBridge and Kinesis channels;
178
+ DynamoDB, RDS instances and clusters, ElastiCache clusters and replication groups, SSM and
179
+ Secrets Manager resources, including ARN name extraction. SNS-to-SQS subscriptions and
180
+ EventBridge rules/targets link queue consumers to source producers, exact without a filter
181
+ and inferred with one. Context, trace, export and scoped orphan reporting cover all kinds;
182
+ SSM SecureString values are redacted, including Terraform/OpenTofu JSON. The schema adds subscription summaries and older
183
+ indexes rebuild. Release level: minor, meada and meada-core 1.3.0 (#658).
184
+ - Orphan infrastructure contracts (#657): `meada status` lists provisioners without uses and
185
+ uses without provisioners only for a contract kind and broker or resource kind with both
186
+ sides in the visible scope. Otherwise `search` and `context` mark the side with
187
+ `no provisioner in the workspace` or `no use in the workspace`, without orphan status noise.
188
+ Matching follows provisioning links, including patterns and root labels. Release level:
189
+ minor for both meada and meada-core in the next release.
190
+
191
+ - Terraform provisioners (ADR 0026): `aws_sqs_queue` and `aws_s3_bucket` join the SQS channel
192
+ and S3 resource contracts by physical name, using an embedded, documented type table. Every
193
+ producer, consumer, writer and reader links to each root's provisioner; overridable names
194
+ link at `inferred` with their variables in the reason. `context` lists the sides and
195
+ provisioners, and `trace` crosses provisioning links both ways. Bounded name patterns link
196
+ literal names at `inferred` (several names: `ambiguous`); the console graph lists provisioner
197
+ sides and provisioning links. Export format 1 gains optional
198
+ `iac_nodes`, `provisioners` and `provisions` arrays. The stored-name sample changes the schema,
199
+ rebuilding older indexes. Release level: minor for both meada and meada-core (#656).
200
+ - Config values (ADR 0025): every scalar of every `*.yaml`, `*.yml` and `*.json` file the walk
201
+ visits, and of the YAML and JSON files under the CI configuration at the root (`.github/`,
202
+ `.gitlab-ci.yml`, `.gitlab/`, `.circleci/`, `.buildkite/`, `.drone.yml`), is indexed with its
203
+ file, key path (jq style, the document index first in a file of several documents), value, type
204
+ and line. `search` finds them with the new kind `value` (exact, then prefix, then substring, over
205
+ values and key paths), and the default search answers with them only when no symbol and no
206
+ contract matches (#639).
207
+ - Config values: a value over 1 KiB is stored cut, marked `(cut)`; a Kubernetes `Secret`'s `data`
208
+ and `stringData` are stored as `redacted`. Lockfiles and files that do not parse are skipped, and
209
+ `meada status` counts the config files read and skipped and the values redacted. Values stay out
210
+ of `meada export`. The index schema changes, so existing indexes are rebuilt (#639).
211
+ - `search` with the kind `value` serves substring matches from an FTS5 trigram table beside the
212
+ B-trees that already serve exact and prefix matches, instead of scanning every row; a query
213
+ under three characters still scans, with the same answer. The table holds about four times the
214
+ text of the key paths and values (21 MB for 5 MB on this repository). The index schema
215
+ changes, so existing indexes are rebuilt (#647).
216
+ - Terraform and OpenTofu config values (ADR 0025): `*.tf`, `*.tofu`, `*.tfvars` and `*.auto.tfvars`
217
+ files are read with `hcl-edit` and `hcl-rs`, and `*.tf.json`, `*.tofu.json` and `*.tfvars.json`
218
+ through the JSON reader, so `search` with the kind `value` finds a team name in an OpsGenie
219
+ routing rule or a queue name in Terraform. The key path runs over the block's type and labels and
220
+ the attribute's name (`resource.aws_sqs_queue.orders.name`), a repeated block `[n]`; a literal
221
+ keeps its type, and an expression or a template is stored as written under the type `expression`
222
+ or `template`. A `.tofu` file shadows the `.tf` file of the same name (#640).
223
+ - Terraform and OpenTofu config values: the `default` of a `variable` with `sensitive = true` (or
224
+ `"true"`) and every value a `.tfvars` file gives a variable of that name are stored as `redacted`,
225
+ and so is a default another file of its directory marks sensitive when that directory holds an
226
+ override file (`override.tf`, `*_override.tf`), which Terraform merges into the others; such a
227
+ default never reaches the index, also when only the override file changes. There, a `.tf` file a
228
+ `.tofu` one hides counts as one that does not parse, since Terraform reads it. A file that does
229
+ not parse is skipped and counted by `meada status` (#640).
230
+ - A Go struct field that keeps a base URL (`c.base`) carries the environment read every
231
+ composite literal of the repository that sets it gives it, directly or through a constructor's
232
+ parameter whose callers in the repository all pass that read, so a method that reads the field,
233
+ directly or through a request wrapper, links through `base_url_env` like the same read written
234
+ inline. Two different reads, a literal by position or of an alias, no literal, a write through
235
+ a selector (`c.base = x`), a constructor with no caller or that a call may reach by a name
236
+ match or through an interface (a method another definition shares the name of), and a literal
237
+ string leave the field
238
+ unknown, as before (#687).
239
+ - A TypeScript class field that is `readonly`, `private` or `#x` and written once, by its
240
+ initializer or by one plain `this.f = v` in the constructor body, is a constant of the class:
241
+ `this.f` in a method folds to it, so `` fetch(`${this.baseUrl}/orders`) `` gets the base URL
242
+ the constructor reads, a Backstage `config.getString` through `app-config*.yaml` included, and
243
+ links through `base_url_env`. A public mutable field, a second or conditional write, a write
244
+ outside the constructor, a constructor parameter and a JavaScript file stay unknown (#688).
245
+ - Backstage's `app-config*.yaml` follows `$include` and reads `$env`: a block moved to a partial (`{
246
+ $include: ./partials/acme.yaml }`, or `./partials/acme.yaml#api` for one key path of it) and a
247
+ value written `{ $env: API_URL }` are read as if inline, so a `config.getString` through them
248
+ links through `base_url_env`. The path resolves against the including file's directory, only
249
+ `.json`, `.yaml` and `.yml` files are read, and includes nest from their own directory. A partial
250
+ is a config input of the index, so editing it alone changes the answer on the next refresh. The
251
+ index schema golden changes (it now lists the stored roles), so existing indexes are rebuilt
252
+ (#689).
253
+ - Backstage `$include` limits: an absolute path, one that leaves the repository, a symbolic link, a
254
+ `${` in the path, another extension, a missing file or key path, a sibling key, a cycle, a depth
255
+ past 8, more than 64 includes from one root, more than 1 MiB grafted into one root and more than 4
256
+ MiB parsed for all the roots of a repository (its files named `app-config.yaml` first, then the
257
+ others in path order; an include counting its file's bytes, or its value's size when YAML aliases
258
+ make it larger, an include past its root's limit included) are not followed (#689).
259
+ - Backstage partials that do not parse: such a partial is parsed once per reading, charged its bytes
260
+ or, holding several documents, what reading them built: their keys stay unread and `meada status`
261
+ names each include with its reason. `$file` stays unread, and a config file past 1 MiB is dropped,
262
+ not parsed by half (#689).
263
+ - Backstage proxy endpoints are read wherever Backstage's proxy backend reads them: under
264
+ `proxy.endpoints`, and, when no `app-config*.yaml` has that key, as the keys of `proxy` that
265
+ start with `/` (the legacy shape, accepted from before Backstage 1.17). A string value is
266
+ `{ target }` in either shape, with the default `pathRewrite`, and `ignorePath`, `prependPath`
267
+ and `pathRewrite` another file gives the same endpoint apply to it. An endpoint inside an
268
+ included partial counts as if inline. With both shapes, in one file or across files, only
269
+ `endpoints` is read. A `getBaseUrl('proxy')` call plus `/inventory/clusters` through any of
270
+ them is `http::GET::/clusters`, linked through `base_url_env` like an object `target`. A
271
+ minor bump (#690).
272
+ - IaC nodes (ADR 0025): every Terraform and OpenTofu `resource`, `data` block and `module` call of a
273
+ `*.tf` or `*.tofu` file is a node with an address (`<type>.<name>`, `data.<type>.<name>`,
274
+ `module.<name>`), a type, a file, its lines and the root module that roots its evaluation (a
275
+ directory no other one calls as a local module). A local module's blocks are instantiated once per
276
+ call under the call's address (`module.orders.aws_sqs_queue.this`), and a literal `count` or
277
+ `for_each` gives one node per `[key]`. Override files (`override.tf`, `*_override.tf`) merge into
278
+ the blocks of their directory, as Terraform applies them (#649).
279
+ - IaC nodes: the references between nodes are stored like calls, followed through `var`, `local` and
280
+ module outputs. `search` finds the nodes with the new kind `iac` (by address, type or physical
281
+ name; the default search leaves them out), `context` on an address shows the type, the physical
282
+ name, the references both ways and the config values, and `trace` walks the references down and
283
+ up. Nodes stay out of `meada export`; the index schema changes, so existing indexes are rebuilt
284
+ (#649).
285
+ - Compose services as IaC nodes: a Compose file (`compose.yaml`, `compose.yml`,
286
+ `docker-compose.yaml`, `docker-compose.yml`) with its override file in the same directory is one
287
+ evaluation unit, rooted at the directory, and each service is a node `services.<name>` of type
288
+ `service`. `depends_on`, `links` and shared networks are references (`via depends_on`, `via
289
+ links`, `via networks.<name>`). `${VAR:-default}` resolves to its default and is marked
290
+ overridable; `${VAR}` stays an unresolved part. A service records its image and its build
291
+ context (a path inside the repository, from its root) for the image contract, and `context`
292
+ shows both. `search` kind `iac`, `context` and `trace` answer for them. The index schema
293
+ changes, so existing indexes are rebuilt; release level minor (#652).
294
+ - CloudFormation and SAM templates as IaC nodes (ADR 0025): a YAML file (the short-form tags `!Ref`,
295
+ `!Sub`, `!GetAtt`, `!Join` and the rest are read) or a JSON file with a `Resources` mapping that
296
+ carries `AWSTemplateFormatVersion` or the SAM transform (`AWS::Serverless-2016-10-31`) is one
297
+ evaluation unit, rooted at the template's path, and each resource is a node addressed by its
298
+ logical id, its type (`AWS::SQS::Queue`, `AWS::Serverless::Function`) the node's type. `Ref`,
299
+ `Fn::GetAtt` (with the attribute in the `via`), the variables of `Fn::Sub` and `DependsOn` are
300
+ references. `search` kind `iac`, `context` and `trace` answer for them; a changed template is
301
+ evaluated again alone. The index schema changes, so existing indexes are rebuilt; release level
302
+ minor (#653).
303
+ - CloudFormation and SAM physical names: the physical name of the types the contract kinds will read
304
+ (queues, topics, buckets, tables, functions, streams, secrets and a few more) is evaluated within
305
+ the template: a parameter's default (marked overridable), `Ref`, `Fn::Sub`, `Fn::GetAtt` and
306
+ `Fn::Join`; a pseudo parameter, an import and any other function are unresolved parts and the name
307
+ a pattern. A parameter with `NoEcho` has its default stored as `redacted` among the config values
308
+ and used for no name (#653).
309
+ - Serverless Framework services as IaC nodes (ADR 0025): a `serverless.yml`, `serverless.yaml` or
310
+ `serverless.json` with a `service` is one evaluation unit, rooted at its path. Each function is a
311
+ node `functions.<name>` of type `Serverless::Function`, named by its `name` or
312
+ `<service>-<stage>-<function>`, with its handler and events (`http GET /orders`, `sqs Queue.Arn`,
313
+ `schedule rate(5 minutes)`) recorded and shown by `context`, and a reference to each resource its
314
+ body names with `Ref`, `Fn::GetAtt` or `Fn::Sub`. The `resources` section is read as
315
+ CloudFormation: each resource is a node at its logical id (#654).
316
+ - Serverless Framework variables: `${self:...}` resolves to the value at its path and the default of
317
+ `${opt:...}` resolves and is marked overridable; `${env:...}`, `${ssm:...}` and the other sources
318
+ are unresolved parts, a `*` in a name and `${...}` in a recorded text. `search` kind `iac`,
319
+ `context` and `trace` answer for them; a changed service is evaluated again alone. The index
320
+ schema changes, so existing indexes are rebuilt; release level minor (#654).
321
+ - Kubernetes objects and Kustomize overlays as IaC nodes (ADR 0025): every YAML or JSON document
322
+ with an `apiVersion`, a `kind` and a `metadata.name` is a node addressed
323
+ `<Kind>[.<group>]/<namespace>/<name>` (no namespace for a cluster-scoped kind). Each directory
324
+ with a `kustomization.yaml` that no other names as a base is an overlay and an evaluation unit:
325
+ its `resources`, `bases` and `components` inside the repository are instantiated under it, each
326
+ node labelled by the overlay, with `namePrefix`, `nameSuffix`, `namespace` and `images` applied
327
+ (#651).
328
+ - Kustomize bases and Kubernetes references: a base stays inside the repository (a `..` that stays
329
+ inside is followed; a remote base, one above the root, through a symlink, in a cycle or past 16
330
+ levels is not), and `meada status` counts the entries not followed. A Service references the
331
+ workloads its selector matches, a workload the ConfigMaps and Secrets of its `env`, `envFrom` and
332
+ volumes and its service account, an Ingress its backend Services, in one namespace and one unit.
333
+ `search` with the kind `iac`, `context` (with the images of a workload) and `trace` answer for
334
+ them as for Terraform's nodes. The index schema changes, so existing indexes are rebuilt (#651).
335
+ - Crossplane compositions, claims and managed resources (ADR 0025): among the Kubernetes nodes,
336
+ `context` names what each object is to Crossplane on a new `role:` line (a composite resource
337
+ definition, a composition, a claim or a composite resource of a kind an XRD of the repository
338
+ defines, a managed resource with `spec.forProvider`, a composed resource), and Crossplane's own
339
+ kinds have no namespace. Each resource a composition creates from a literal `base`
340
+ (`spec.resources`, or a function patch-and-transform pipeline step) is a node
341
+ `<composition>/<resource>` of the base's kind, named by its `crossplane.io/external-name`
342
+ annotation or `metadata.name`; a managed resource is named by its external name (#655).
343
+ - Crossplane references, in one unit: a claim to the XRD of its composite kind, a composite resource
344
+ to its XRD, a `compositionRef` to its composition, an XRD to its default and enforced composition,
345
+ a composition to the XRD it composes and to each resource it creates, and a created or managed
346
+ resource to the XRD or `CustomResourceDefinition` of its kind. Patches and functions are not
347
+ evaluated: a name a patch sets, or a base with no name, is the pattern `*`, and a step running any
348
+ other function creates no node. The index schema changes, so existing indexes are rebuilt; release
349
+ level minor (#655).
350
+ - Static evaluation of Terraform names (ADR 0025): an IaC node's physical name (its `name` argument)
351
+ and each `count` and `for_each` are evaluated with `hcl-rs`'s evaluator and Meada's pure functions
352
+ (string, collection and conversion functions and `jsonencode`), from variable defaults, the root's
353
+ `terraform.tfvars`, `*.auto.tfvars` and their JSON forms, locals, local module inputs and outputs
354
+ per call, `each` and `count.index`, without running Terraform or reaching the network, so a
355
+ `for_each` over a variable gives one node per instance. `context` lists under `overridable:` the
356
+ root variables a name went through, by their default or a var file. A changed Terraform file or
357
+ var file evaluates again only the root modules whose unit holds it. The index schema changes, so
358
+ existing indexes are rebuilt (#650).
359
+ - Terraform names never evaluated: data sources, resource attributes, registry modules,
360
+ `terraform.workspace`, `-var`, `-var-file`, `TF_VAR_` and sensitive variables (marked by any of
361
+ their blocks, override files included, and every variable of a directory holding an override file
362
+ and a Terraform file that does not read or a `.tofu` file hides): such a part of a name is a `*`
363
+ and the name a pattern, shown as `pattern "orders-*"` by `search` and `(pattern)` by `context`,
364
+ and linked by nothing yet. A value over 64 KiB, an expression that could make over 1 MiB and a
365
+ root's evaluation past 64 MiB stay unresolved (#650).
366
+ - TypeScript consumers through `new URL(x)`: `new URL(x)` with one argument is `x` (unless the file
367
+ declares a `URL` or imports one from a relative path), and `u.toString()`, `u.href`, `String(u)`
368
+ and `` `${u}` `` pass the URL through, in a constant or built in place, so a `fetch` or a client
369
+ wrapper called with one links to its route and a base URL read from the environment shows its
370
+ `via`. A change through `u.searchParams`, `u.search` or `u.hash` keeps the path; a write to any
371
+ other member of a `new URL` constant, written in parentheses or a type assertion too, leaves it
372
+ unresolved, also through a destructuring or `for (.. of ..)` target, `++`, `Object.assign` or
373
+ another name holding it, or with the target in parentheses or an assertion, as does such a
374
+ write to a sealed field set where it is declared or in its constructor
375
+ (`this.url.pathname = ..`) (#685).
376
+ - TypeScript consumers through `new URL(reference, base)`: the two arguments read as the join the
377
+ WHATWG URL Standard defines (RFC 3986 section 5.2 for these references), so an absolute reference
378
+ is itself, `//host/x` takes its host, `/orders` replaces the base's path and `orders` joins the
379
+ base's directory (`https://h/api/` keeps `api`, `https://h/api` does not). Over a base read from
380
+ the environment (or a hole) an absolute path keeps the base as its lead, so `/orders` is
381
+ `http::GET::/orders` with `via env:API_URL`; a relative reference, one that starts with a read,
382
+ and a query or a fragment alone stay unresolved, and a parameter on either side is resolved at the
383
+ call sites (#686).
384
+ - `new URL(reference, base)` bases: a base is placed only when its scheme leads it, so a proxy's
385
+ `${X}/fetch/https://api.example.com/` is an opaque base, not a link to that host, and every
386
+ reference loses its dot segments. Swift's `URL(string:relativeTo:)` over a literal base goes
387
+ through the same resolver and follows the same rules; over a base read from the environment it
388
+ stays unresolved (#686).
389
+
390
+ ### Changed
391
+
392
+ - Development and test builds optimize the main `meada` package at level 1 to reduce the
393
+ resident code footprint of the expanded indexing and contract readers (#711).
394
+ - Kotlin: a name read or called in a lambda looks for a local or local function of the code
395
+ around it in one climb, not one from every enclosing lambda: a file of 300 nested `apply`
396
+ blocks indexes in about 12 s instead of over 100 s (debug build), with the same answers (#711).
397
+
398
+ - A refresh reads the values of the files it did not change from a values cache beside the index
399
+ (`values.db`, ADR 0027) instead of parsing them again: on this repository, a one-line edit of a
400
+ Rust file refreshes in 1.4 s instead of 3.4 s. The refreshed index still equals a cold one, and
401
+ deleting the cache costs only time (#611).
402
+ - A refresh builds no resolver for a group it keeps, resolves each call of a changed group once,
403
+ writes communities again only when the call graph moved, and the actix-web reader skips the
404
+ lookups whose answer it does not use: on this repository a one-line edit of a Rust file
405
+ refreshes in 1.0 s instead of 1.5 s, with the same index (#610).
406
+ - A refresh summarizes a contract configuration again only when its bytes, the IaC nodes it
407
+ read or a path it looked at changed: 60 ConfigMaps of 290 KB refresh with no change in 0.01 s
408
+ instead of 4.5 s (debug build), and a removed or added Lambda handler or Compose build path
409
+ still moves its answer (#711).
410
+ - `search` with the kind `value` reads the value of only the rows its answer shows (each match
411
+ keeps just its sort key), so a broad query such as `e` no longer formats every matching value
412
+ before the budget cuts it (#711).
413
+
414
+ ### Fixed
415
+
416
+ - A Java AWS SDK request no longer names a table, topic, bucket or queue its builder had before
417
+ the builder changed (#719). A builder changes in place, so a name is `exact` only when every
418
+ mention of the builder is a form the reader follows: a setter, `.build()`. Any other mention
419
+ leaves the side unresolved: the builder handed to a call or captured, `applyMutation`,
420
+ `copy(consumer)`, an alias at any depth, and a use the reader does not model (a cast, a
421
+ ternary). A value built first keeps its name, as an immutable copy does, except in a loop the
422
+ builder outlives. A request is judged whole: one such entry leaves the others unresolved.
423
+ The check reads a file once, so its cost is linear in the calls.
424
+ - A Java AWS SDK request built by a lambda or a class that runs after its builder changed, one
425
+ its helper assigns again as a parameter, one a caller passes on after its builder changed, a
426
+ builder field hidden by a local, one set from an initializer or another file, one handed to
427
+ caller code by `applyMutation` and a request type another type or an import shadows name no
428
+ table either (#719).
429
+ - A Java AWS SDK request whose builder is set again in a loop around the one its value is built
430
+ in, or inside the request's own expression, names no table either (#719).
431
+ - Terraform static evaluation charges the template text `hcl-rs` parses again at each
432
+ evaluation in a `for`, not only the bytes an expression makes: a template in a `for` over
433
+ thousands of elements is unresolved (`*`) before it runs, where one 24 KB root took seconds
434
+ per resource and minutes in all. A read such as `var.x[0]` in a `for` is charged the copy of
435
+ `var` it makes each time. A refused expression spends the bytes it went through (its text and
436
+ the roots it read), at most the 1 MiB each one spent before, and a literal name that fits one
437
+ value stays exact once the work is spent. A short template (`"${a}-x"`) in a `for` over 2,000
438
+ elements still resolves; one of 40 interpolations resolves over 100 elements, no longer over
439
+ 200 (#714).
440
+ - `meada mcp` over stdio answers calls a client sends without waiting for each reply (#704).
441
+ Each call refreshes the index, and a refresh failed at its first write with `database is
442
+ locked` when another call was writing. Now the calls of one server run one refresh at a time
443
+ and wait for it with no timer, sharing the next run; a call that meets its lock elsewhere
444
+ (opening the index, querying it) waits for the refresh too, past the 10 s busy timeout. A
445
+ batch after a change costs about one refresh more than an unchanged one (debug build, Meada's
446
+ own checkout: 50 calls 21 s against 15 s). Across processes, a refresh with nothing to write
447
+ takes no write lock and one that meets another process's writer waits for its commit and
448
+ starts over; a wait past 10 s there still answers `database is locked`, and that server's
449
+ calls wait behind its refresh as long as it takes.
450
+
451
+ - Terraform: a `for` binding a key over a set held in a local or a variable (`local.s` from
452
+ `toset(...)`, a chain of locals, a variable declared `type = set(...)`) is unresolved
453
+ instead of answering the index as an exact key, as it already was over a written `toset(...)`
454
+ (#720). A set reached through an attribute, an index or another call stays a ceiling (#717).
455
+ - Terraform: a value that enters a variable declared `set(T)` (its default, a var file's value, a
456
+ module argument, an override's default) is converted to elements of type `T`, then sorted and
457
+ deduplicated as cty does, so `tolist(var.s)`, `length(var.s)` and `join` over `["b", "a", "a"]`
458
+ see `a`, `b`, and a `set(string)` of `[10, 9]` keeps the strings `"10"` and `"9"` in string
459
+ order. An element Meada cannot convert with certainty leaves the value unresolved (#720).
460
+ - Terraform: an override file that replaces the `type` of a variable whose own block declares a
461
+ set type is now converted as Terraform converts it: the default is converted to the set first,
462
+ then to the new type (`list(string)` gives the set's elements in set order, `any` and `set(string)`
463
+ keep the set; a default an earlier override gave is converted the same way when a later
464
+ one retypes it), and one Terraform rejects (a tuple) gets no exact name. OpenTofu 1.13 and later convert the default
465
+ once, to the final type, and name other instances; Meada follows Terraform (#740), except for a
466
+ variable with a block in a `.tofu` or `.tofu.json` file, which Terraform does not read: it is
467
+ unresolved where the two conversions differ. Known gap: indexed end to end, the four cases tried
468
+ of a `for_each` over a variable retyped to a list got one pattern name where Terraform creates an
469
+ instance per element, and none got a wrong exact name; the cause is open (#783).
470
+ - An Alertmanager configuration with a matcher regex Go's `regexp` refuses (an unclosed
471
+ group, a leading `*`, a backward range, a lookahead) is unreadable, as Alertmanager refuses
472
+ to load it: it gives no alert side or link, where its valid routes kept an `exact` link,
473
+ and `meada status` counts the file under `unreadable`. Only a syntax error established as
474
+ a `regexp/syntax` error code counts; an expression past Meada's own budgets or syntax it
475
+ does not read stays unmatched with the other routes linked (#718).
476
+ - AWS SDK forms in Java, Go and C# follow the ADR 0026 rule TypeScript and Python already
477
+ followed: an EventBridge entry without `EventBusName` produces to `default`, and an SNS
478
+ publish to a phone number or endpoint names no topic. A request Meada cannot see whole (a
479
+ builder from `toBuilder()` or from a factory of the repository's own, a helper's result) keeps
480
+ its unresolved side. TypeScript and
481
+ Python now read the S3, SSM and Secrets Manager operations Java, Go and C# read
482
+ (`DeleteObject`, `HeadObject`, `ListObjects`, `ListObjectsV2`, `PutParameter`,
483
+ `DeleteParameter`, `DeleteParameters`, `PutSecretValue`, `UpdateSecret`, `CreateSecret`,
484
+ `DeleteSecret`); DynamoDB transactions stay TypeScript and Python only (#660).
485
+ - `snapshot publish` no longer publishes the old graph under a new commit when only a contract
486
+ configuration or a path its summary looked at changed (a removed Lambda `worker.zip`, a
487
+ Compose build context): the index is fresh only while all of them are as it read them (#711).
488
+ - An image's Helm values file is any YAML file with a `values` word in its name, as for alerts,
489
+ so `prod-values.yaml` declares image consumers, as `values.prod.yml` already did, and
490
+ `valuesets.yaml` does not (#711).
491
+
492
+ - Python: an import inside a function names its library in that function again, so
493
+ `from requests import get` and `import requests as r` there are HTTP consumers, and
494
+ `import json as requests` there hides the module's `requests` (#668).
495
+ - Python framework and Go router tables retain stable identities in optimized builds, so
496
+ Flask blueprints keep their mounted routes and standard Go mux matching stays consistent (#711).
497
+
498
+ - TypeScript and JavaScript URL consumers respect lexical bindings and writes of `String`
499
+ (#683). A callback named `String` no longer invents a route or host, and a local binding
500
+ leaves the global conversion in other scopes intact. Non-strict block functions follow
501
+ Annex B's enclosing binding; modules, classes and strict prologues retain block scope.
502
+
503
+ - Image runners and links retain each evaluation root when Kustomize overlays reuse the same
504
+ workload and normalized image. Repeated image evidence within one workload and root still
505
+ collapses to one side (#711).
506
+ - A symbol's `context` shows the level, reason and provider of inferred HTTP call links whose
507
+ recorded environment base selects a declared `base_url_env` peer, including through fields
508
+ and Backstage config partials. Editing only a partial refreshes that explanation (#683).
509
+ - Resource SDK reader call sites retain their identities while traces follow writer-to-reader
510
+ data flow and its reverse, show the actual function/location, and continue through the
511
+ reader's body. Shared partial reads and process membership use the same direction; HTTP
512
+ and package calls keep their existing behavior (#659, #660).
513
+
514
+
515
+ - Terraform and OpenTofu config values redact an `aws_ssm_parameter` resource's `value` when
516
+ its literal `type` is `SecureString`, in HCL and Terraform JSON, regardless of attribute order.
517
+ Ordinary `String` parameters keep their values (#709).
518
+ - TypeScript and JavaScript URL folding requires the runtime global or the named `URL` export
519
+ of `url` or `node:url`. Unknown imports, repository aliases, other exports and shadowed
520
+ CommonJS loaders no longer invent HTTP consumers or links (#709).
521
+ - CloudFormation nodes and references survive cold indexing and warm refreshes when a qualifying
522
+ template is named `compose.yaml`: its resource types decide ownership before its filename,
523
+ without changing real Compose ownership (#709).
524
+ - A YAML document whose anchors and aliases expand past the nesting limit (128 levels) is
525
+ reported unreadable and skipped, where it could abort meada (#646).
526
+ - Crafted IaC and YAML files no longer exhaust memory or time while indexing: long
527
+ CloudFormation parameter defaults joined or substituted many times, names built through more
528
+ than 32 Terraform variables or CloudFormation parameters (now unresolved), YAML anchors nested
529
+ around a large node, Kustomize files listed many times or reached through a diamond of bases,
530
+ thousands of `images` rules, Ingress hosts past 253 bytes and volume names past 63 (now left
531
+ out), an `Fn::Sub` that names its variable twice at every level, Terraform objects of
532
+ thousands of keys (a file whose objects pass 2^24 key comparisons is now unreadable), costly
533
+ `.tfvars` values (now given but unresolved) and long `trim` and `toset` arguments (#646, #649,
534
+ #651, #653).
535
+ - An Alertmanager route expression of case-insensitive Unicode classes (`(?i)\p{Any}` written
536
+ hundreds of times) no longer takes minutes to compile on every `export` and `status`, nor do
537
+ hundreds of route configurations compile a megabyte automaton each: the expressions of one
538
+ linking pass share 2^22 code points of case folding (counted only in ranges that hold a cased
539
+ letter, a bracket's classes as folding leaves them), 4096 Unicode classes and 16 MiB of
540
+ automata, in equal parts per routing scope and expression, so what links does not depend on
541
+ the repository asking. Past its part an expression stays unmatched (`status` shows its matcher
542
+ as an orphan, not a limit), and the same expression in route configurations of as many
543
+ expressions is compiled once (#672).
544
+ - A long label matched by an Alertmanager route expression of many automaton positions no longer
545
+ runs the expression over it for every route: `.*a.{1000}a.*` against a label of 300,000 bytes
546
+ took 43 s for each route (debug). Before reading a value, each condition is charged a step per
547
+ automaton position (a state that reads nothing, such as an assertion or an empty capture,
548
+ included) and byte offset it may start at, or the bytes it reads for a comparison, against a
549
+ ceiling of 2^26 steps per pass apart from the evaluation ceiling, so that label stops before
550
+ matching and `status` reports the evaluation limit, while route visits and evaluations count as
551
+ before (#711).
552
+ - Alerts: a regular expression Go refuses for a repetition operator stacked on another (`a**`,
553
+ `a{2}*`) no longer links (#711).
554
+ - Alerts: an AlertmanagerConfig route links `inferred`, since prometheus-operator also matches
555
+ the alert's namespace, which Meada does not read (its consumers say `(AlertmanagerConfig
556
+ namespace)`); a Grafana rule group repeated with `count` or `for_each` declares no rule (it may
557
+ be made zero times); a file with a `values` word in its name (`prod-values.yaml`,
558
+ `values.prod.yaml`) is Helm input, not just one starting with `values`; a quoted matcher value
559
+ reads Alertmanager's escapes (`\n`, `\"`, `\\`), so `"a\.b"` keeps its backslash instead of
560
+ invalidating the route and its siblings; and the 4 MiB file ceiling charges the text a rule or
561
+ route stores, so 2,000 small rules (187 KB) are no longer dropped (#672).
562
+ - A Python file of thousands of AWS SDK operations on clients a factory function returns no
563
+ longer takes minutes to index: the operations one reader asks about in a file keep the answers
564
+ no limit cut and share a budget of 2^18 steps, one operation taking up to all that is left
565
+ (each still taking 16 once it is spent, so five factories of 2,000 returns resolve on their
566
+ first operation), and a call passing thousands of clients to one function, or forwarding them
567
+ through a wrapper to the Google Cloud and Azure readers, no longer copies them for every value
568
+ it reads (#660, #668, #669).
569
+ - Terraform: an object written after a `-`, a number or a `/`, or after a quote or heredoc end
570
+ inside a template directive's body, now counts toward the 2^24 key comparisons a file may
571
+ hold, where a file of them could take minutes to parse; a file with a heredoc whose first
572
+ line starts with its identifier is now unreadable, since the parser read it otherwise than
573
+ Terraform and could hide such objects behind it (#640); a JSON
574
+ var file of tens of thousands of keys reads in linear time, where it took over half a minute;
575
+ and a var file Terraform loads that does not read (broken, too wide or past 1 MiB) leaves the
576
+ variables it may give unresolved, where their defaults stood in (#650).
577
+ - Backstage proxy: a `proxy.endpoints`, a whole `proxy` or a root behind an `$include` Meada
578
+ does not follow counts as the endpoints table, as Backstage reads (or refuses) whatever the
579
+ include gives, so the legacy `proxy['/<ep>']` keys beside it or in another file no longer link
580
+ a call; an include whose `#` key path's last key is absent does not, since Backstage leaves that
581
+ key out (#709).
582
+ - Backstage `$include`: an `app-config*.yaml` that is one `$include` is the file it names, a root
583
+ or a partial of more than one YAML document is unreadable, and an include of the file and key
584
+ path being read keeps its `$include` as written rather than being a cycle, all as Backstage's
585
+ config loader reads them (#709).
586
+ - Serverless: a function with no `name` is named after `--stage` first, so `context` lists its
587
+ name as overridable through `opt:stage` (at `provider.stage`'s line, or the function's when the
588
+ file has no stage) and the name links `inferred`; `${self:provider.stage}` still reads the file
589
+ and is no override (#709).
590
+ - Authorization: an `added_by` a team operator wrote while no GitHub grant provider was
591
+ configured no longer decides eligibility once `[oidc.github]` is enabled. Under the provider the
592
+ console stamps each `added_by` it writes with `added_by_time` (its own clock, never the
593
+ submitted text; part of the version id), and without it writes none; Postgres migration 10
594
+ keeps the time the provider's first permissions set started (`<schema>.permission_state`), and `meada github-app roles` reports an addition on the
595
+ host whose `added_by` has no time, or one no later than that set's second, `unattributed` and
596
+ excludes it whatever its roles. Entries saved before this version carry no time, so under the
597
+ provider their additions are excluded until the global operator writes a reviewed
598
+ `added_by_time` or a team operator adds them again; `composeEntries` takes the time as its
599
+ fourth argument (#454).
600
+ - A query no longer reopens each peer's index: the engine refreshes and reads the connection it
601
+ holds, so a peer is never refreshed in one file and read from another (#443).
602
+ - GitHub App: a 403 `Resource not accessible by integration` with quota left (no `retry-after`,
603
+ `x-ratelimit-remaining` above 0) is a permission failure, not a throttle: `github-app roles`
604
+ passes it to the next installation unmarked, records the repository as `forbidden` (no rows, a
605
+ warning) when every installation answers so, and the installations stay eligible for the role
606
+ check and keep minting. A 403 or 429 with `retry-after` or an empty quota still
607
+ throttles, as does any 403 outside the role check's collaborators listing (ADR 0013 amended,
608
+ #452).
609
+ - prove-meada scripts: the console page checks sign in again when a route lands on the sign-in page
610
+ and fail the route that stays there, the Helm overlays `values-identity.yaml` and
611
+ `values-workspaces.yaml` render in their stack (as `scripts/helm-check` does) instead of failing
612
+ alone, and `console.py start --bin` resolves a relative path against the caller's directory (#679).
613
+ - `meada export`, `meada status` and the other commands that print their result once done no
614
+ longer panic when the reader closes its end early (`meada export | head -1`, `| true`): the rest
615
+ of the output is dropped and the command ends as it would, where it panicked with "failed
616
+ printing to stdout: Broken pipe (os error 32)" and exited 101. `meada decide` and `meada mcp`,
617
+ which never panicked, still stop with a "Broken pipe" error and exit 1 (#711).
618
+ - Kustomize: with two bases of their own `namePrefix` that write the same names, a Deployment no
619
+ longer references the other base's ServiceAccount, nor an Ingress the other base's Service. A
620
+ Service reference, and a `serviceAccountName` of the kinds Kustomize renames (Pod, Deployment,
621
+ StatefulSet, DaemonSet, ReplicationController, Job, CronJob), resolve as Kustomize's name
622
+ reference does once the tree is built: among the objects of the referrer's namespace (none and
623
+ `default` alike) a stage renamed or moved from the name as written, the only one, else those
624
+ whose prefix and suffix stages end as the referrer's; with none left, the object called by the
625
+ name as written, a final name included, and with several (a tree Kustomize refuses), none.
626
+ Another kind's account, or the deprecated `serviceAccount`, which Kustomize leaves alone, names
627
+ the account called so. An empty `namespace` in a kustomization no longer sets one (#711).
628
+ - Ingress: a path Meada cannot read as a literal prefix (`/store/(.*)`, `/api/*`) no longer drops
629
+ out of the routing table, where a shorter rule then claimed its URLs; it is an unread mount at
630
+ its literal head cut at its last slash. A `use-regex` annotation or a missing `pathType` also
631
+ leaves the path unread, and so does a path left out (an ImplementationSpecific catch-all); a
632
+ table past its ceilings (64 rules, read or not) leaves every host of the Ingress unread, not
633
+ only the hosts read before the cut (#711).
634
+ - Kustomize `components` change what the kustomization that lists them holds, its bases'
635
+ objects included, as Kustomize applies them; they were instantiated as one more base, so a
636
+ component's `images` rule never retagged the overlay's workloads. Each object a component is
637
+ handed counts against the 50,000 entries one overlay walks, so components reaching one another
638
+ along many paths, or many objects through a long list of them, stop there (#711).
639
+ - HTTP: overlays that repeat one Ingress or Service per environment no longer make a route to a
640
+ single provider `ambiguous`; distinct providers, or a route as long that reaches no code,
641
+ still do. A decision recorded for such a route is now stale; `meada decide --prune` removes it (#711).
642
+ - Images: a module run from a local path (an archive or a directory) in one root no longer drops
643
+ the image another root runs it from, with its environment and provisions; only that root runs
644
+ code without an image (#711).
645
+ - Terraform: `split(",", "")` gives one empty element (a `count` over its length made no node), and
646
+ an IaC name pattern needs three letters or digits besides its wildcards (`*.*.*.*` matched any
647
+ dotted name) (#711).
648
+ - Terraform: an object walks its keys in lexical order, whether a variable or local binds it or the
649
+ expression builds it (a literal, a `merge`): a `for` over it or a `jsonencode` of it gave an
650
+ `exact` name in written order, and a `for` whose collection contains an object whose keys are
651
+ known only once evaluated (a computed key, a comprehension) is now `*` (#711).
652
+ - Terraform: integer arithmetic is exact, as Terraform's: a result past `u64` or below `i64` (`0 -
653
+ 18446744073709551615`), a division by zero or with a remainder (`7 / 2`) and arithmetic on a
654
+ fraction leave that part of the name `*`, also on a `for` variable, where the evaluator printed a
655
+ cast, wrapped or floating-point value as an `exact` name. So do a number literal or `tonumber`
656
+ past them, with more digits than a float holds or that a float writes with an exponent
657
+ (`18446744073709551616` printed `1.8446744073709552e19`), a JSON number written with a fraction or
658
+ an exponent and a negative zero (`-0`, `0 * -1` printed `0`). Such a value in a var file is given
659
+ but unresolved, so the variable's default no longer stands in for it (#711).
660
+ - Terraform: `toset` orders its elements as Terraform does (numbers by value, `false` before
661
+ `true`, a null last, strings with numbers or bools as strings), where it kept a number's or a
662
+ bool's first order: `tolist(toset([10, 9]))[0]` was an `exact` `10` for Terraform's `9`. A set of
663
+ collections, in Terraform's hash order, and a set of numbers and bools, which Terraform refuses,
664
+ are `*` (#711).
665
+ - Terraform: a null or a collection interpolated into a name (`"q-${null}"`, `"q-${[1]}"`), which
666
+ Terraform refuses, is `*`, where it gave the `exact` names `q-null` and `q-[\n 1\n]` (#711).
667
+ - Terraform: arithmetic on a `for` variable in a `.tfvars` file (`[for x in [1, 2] : x * 2][1]`)
668
+ resolves, as Terraform evaluates it, where the value was given but unresolved (#711).
669
+ - Terraform: a `%{ for }` directive's collection is read as any other expression, where its keys
670
+ kept their written order and a number its float text (`%{for k, v in {b = 1, a = 2}}` gave
671
+ `b1a2`, Terraform `a2b1`); a negative zero there is `*`. An object of several keys inside a var
672
+ file's template, with or without line comments, no longer drops the value for the default (#711).
673
+ - Terraform: `tolist` and `tomap` convert their elements to one type, as Terraform does, where
674
+ they kept each element's type: `jsonencode(tolist(["a", 1]))` gave an `exact` `["a",1]` for
675
+ Terraform's `["a","1"]`; collections unify as cty does (`[[1], ["a"]]` to `[["1"],["a"]]`). A
676
+ number with a bool and a list's null beside a collection, which Terraform refuses, are `*` (#711).
677
+ - Terraform: a `for` over `tolist`, `toset` or `tomap` (`{for o in tolist(var.items) : o.name =>
678
+ o}`) costs as a `for` over its argument, so forty objects from a var file expand where the
679
+ estimate, the argument's size squared, left the resource `*` past about a kilobyte (#711).
680
+ - Terraform: a `for` or `%{ for }` binding a key over `toset(...)` (`for k, v in toset(x)`) is
681
+ `*`, where the key was the index (`q-0`) and Terraform's is the element (#711).
682
+ - Images: a direct path that went through a value a deployer can override (`${CTX:-./app}`)
683
+ runs code `inferred`, not `exact`; a repository's literal image and its own pattern matching
684
+ the same runner are one link, not two `ambiguous` ones; a Helm `image.registry` prefixes
685
+ `image.repository` (a templated one as an unresolved segment), where the runner named a Docker
686
+ Hub image; and an unresolved image name (`image::*`, from `docker/metadata-action`) is no
687
+ `status` orphan (#711).
688
+ - Compose: an override file's `build` with no `context` keeps the base service's context, where
689
+ it built from the override's directory, and the `!reset` and `!override` tags clear or replace a
690
+ base value. A `build` context Docker reads as a git repository (`git@github.com:a/b.git`,
691
+ `github.com/a/b`) is no local directory, so it runs no code of the repository. SAM: a
692
+ function with no `CodeUri` of its own takes `Globals.Function.CodeUri`. Kustomize: a
693
+ `bitbucket.org/` base is remote, as `github.com/` and `gitlab.com/` ones are, where one without
694
+ `?ref` counted as missing (#711).
695
+ - SDK names (GCP and Azure, and AWS in TypeScript): a request field written through a computed
696
+ key (`{['name']: ..}`) or a spread of another object (a spread of a spread too), or written
697
+ after the call inside a loop statement that also holds the call, leaves the name unresolved;
698
+ each gave an `exact` link to the name first written (#711).
699
+ - AWS SDK: a request changed after it is made names no resource: a TypeScript command input
700
+ (SQS's too) whose field is assigned again before the `send`; a Java builder held in a local or
701
+ a `final` field that is set again or handed to another call, itself, through a chain off it or
702
+ through a local holding it (`b.topicArn(..)` before `client.publish(b.build())`), also for SQS and Azure Service Bus and Event Hubs builders; and
703
+ a named entry an inline request holds (an EventBridge entry in C# or Go, an entry builder in
704
+ Java); and a Go request replaced whole through its pointer (`*input = sqs.SendMessageInput{..}`).
705
+ Each gave an `exact` link and provision to the name first written. A TypeScript field
706
+ read off a local object (`{Bucket: cfg.bucket}`) now names its bucket (#711).
707
+ - TypeScript and JavaScript: a generator (`function*` and `async function*`, declared or as an
708
+ expression, a `*method()` of a class or an object) returns its iterator, so a `return new
709
+ Storage()` in one no longer makes it a client factory; it gave an SDK resource (Pub/Sub, Cloud
710
+ Storage, Azure Service Bus and Blob) and an `exact` provision to code that never holds the
711
+ client (#711).
712
+
9
713
  ## [1.2.0] - 2026-11-04
10
714
 
11
715
  A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
@@ -1297,7 +2001,8 @@ and `trace` from the two longest processes. The spec adds about 0.3 MB and 0.03
1297
2001
  The rise of the single-file reindex since 2026-10-14 predates it (specs #22 and #23), and at
1298
2002
  692 files it is close to its target.
1299
2003
 
1300
- [Unreleased]: https://github.com/ClaudioMascaro/meada/compare/v1.2.0...HEAD
2004
+ [Unreleased]: https://github.com/ClaudioMascaro/meada/compare/v1.3.0...HEAD
2005
+ [1.3.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.3.0
1301
2006
  [1.2.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.2.0
1302
2007
  [1.1.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.1.0
1303
2008
  [1.0.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.0.0
package/README.md CHANGED
@@ -18,7 +18,7 @@ Escolha a linha que combina com o que você já tem. Todos os canais entregam o
18
18
  | Rust | `cargo install meada` | `meada mcp` |
19
19
  | Linux ou macOS | o instalador de shell abaixo | `meada mcp` |
20
20
  | Qualquer sistema | o arquivo do seu sistema nas [releases do GitHub](https://github.com/ClaudioMascaro/meada/releases), com `meada` no `PATH` | `meada mcp` |
21
- | Docker | `docker pull ghcr.io/claudiomascaro/meada:1.2.0` | a linha `docker run` em [Conectar um agente](#conectar-um-agente-mcp) |
21
+ | Docker | `docker pull ghcr.io/claudiomascaro/meada:1.3.0` | a linha `docker run` em [Conectar um agente](#conectar-um-agente-mcp) |
22
22
 
23
23
  ```sh
24
24
  # Instalador de shell (Linux e macOS)
@@ -75,7 +75,7 @@ Com Docker (Linux e macOS):
75
75
  "mcpServers": {
76
76
  "meada": {
77
77
  "command": "sh",
78
- "args": ["-c", "exec docker run -i --rm --network none --user \"$(id -u):$(id -g)\" -v \"${PWD%/*}:${PWD%/*}\" -w \"$PWD\" ghcr.io/claudiomascaro/meada:1.2.0 mcp"]
78
+ "args": ["-c", "exec docker run -i --rm --network none --user \"$(id -u):$(id -g)\" -v \"${PWD%/*}:${PWD%/*}\" -w \"$PWD\" ghcr.io/claudiomascaro/meada:1.3.0 mcp"]
79
79
  }
80
80
  }
81
81
  }
@@ -97,7 +97,7 @@ ler os níveis de uma resposta. No Claude Code:
97
97
 
98
98
  ```sh
99
99
  mkdir -p ~/.claude/skills/meada
100
- curl -fsSL https://raw.githubusercontent.com/ClaudioMascaro/meada/v1.2.0/skills/meada/SKILL.md -o ~/.claude/skills/meada/SKILL.md
100
+ curl -fsSL https://raw.githubusercontent.com/ClaudioMascaro/meada/v1.3.0/skills/meada/SKILL.md -o ~/.claude/skills/meada/SKILL.md
101
101
  ```
102
102
 
103
103
  Outros agentes: veja [Agentes e MCP](https://claudiomascaro.github.io/meada/mcp/#skill-para-agentes).
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "Apache-2.0",
21
21
  "name": "@meada/meada",
22
- "version": "1.2.0"
22
+ "version": "1.3.0"
23
23
  },
24
24
  "node_modules/detect-libc": {
25
25
  "engines": {
@@ -48,5 +48,5 @@
48
48
  }
49
49
  },
50
50
  "requires": true,
51
- "version": "1.2.0"
51
+ "version": "1.3.0"
52
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "artifactDownloadUrls": [
3
- "https://github.com/ClaudioMascaro/meada/releases/download/v1.2.0"
3
+ "https://github.com/ClaudioMascaro/meada/releases/download/v1.3.0"
4
4
  ],
5
5
  "bin": {
6
6
  "meada": "run-meada.js"
@@ -89,7 +89,7 @@
89
89
  "zipExt": ".tar.xz"
90
90
  }
91
91
  },
92
- "version": "1.2.0",
92
+ "version": "1.3.0",
93
93
  "volta": {
94
94
  "node": "18.14.1",
95
95
  "npm": "9.5.0"