@meada/meada 1.1.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 +924 -1
- package/README.md +4 -4
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,927 @@ 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
|
+
|
|
713
|
+
## [1.2.0] - 2026-11-04
|
|
714
|
+
|
|
715
|
+
A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
|
|
716
|
+
package reading (PEP 440 specifiers, uv sources, Go `replace` by a held module, `fetch` URLs a
|
|
717
|
+
function builds), resolution in the Rust, TypeScript and Gradle packs, the console's versions
|
|
718
|
+
page for a named workspace, the proposal server in the Compose and Helm recipes, SCRAM channel
|
|
719
|
+
binding to Postgres, CLI messages in Spanish, a generated first password for the console's
|
|
720
|
+
default `admin` account instead of a published one (#579), a refresh that keeps the language
|
|
721
|
+
groups no changed file touches (#391), Backstage and HTTP contract reading (tier d1, #613 to #621), and the fixes of tiers b6 to c5. The stored
|
|
722
|
+
manifest summary changes, so existing indexes are rebuilt once on first use. `meada-core` 1.2.0 deprecates `msg::pt()` in
|
|
723
|
+
favour of `msg::lang()` (`msg::lang() == msg::Lang::Pt`), types `effective::Diagnostic::code` as
|
|
724
|
+
`DiagnosticCode` (the JSON is unchanged) and makes `named::message_problem("")` return `Some`;
|
|
725
|
+
the new `msg::Lang` and `effective::DiagnosticCode` are `#[non_exhaustive]`, so a match on
|
|
726
|
+
either needs a wildcard arm. A crate that declares `meada-core = "1.1"` meets the last two
|
|
727
|
+
changes on `cargo update`, and `=1.1.0` stays on the old API. The tree, the `meada-core` pin, the
|
|
728
|
+
Dockerfile, the compose defaults and the Helm chart declare `1.2.0`, and the `v1.2.0` tag goes
|
|
729
|
+
on the `release/1.2` branch, cut from this entry's merge on main. Publication
|
|
730
|
+
(crates, the staged npm package, the GitHub draft release) belongs to the maintainer.
|
|
731
|
+
Release notes are available in
|
|
732
|
+
[pt-BR](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.2.0.md),
|
|
733
|
+
[English](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.2.0.en.md) and
|
|
734
|
+
[Spanish](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.2.0.es.md).
|
|
735
|
+
|
|
736
|
+
### Added
|
|
737
|
+
|
|
738
|
+
- Backstage backends: the router a backend plugin gives its `httpRouter`
|
|
739
|
+
(`coreServices.httpRouter`) is served under `/api/<pluginId>` when `createBackendPlugin` writes
|
|
740
|
+
its `pluginId` as a literal or as a `const` of the file bound to one, so two plugins with the
|
|
741
|
+
same relative path no longer collide, and a URL
|
|
742
|
+
that starts with `discovery.getBaseUrl('<id>')` (held by a constant or written in place) starts
|
|
743
|
+
at `/api/<id>`, its link's reason naming the plugin's mount (as does a hostless call of a route
|
|
744
|
+
the plugin serves in its own repository). A plugin whose `pluginId` cannot be read stays at the
|
|
745
|
+
root, and `meada status` names it. TypeScript and JavaScript functions now give their `return`
|
|
746
|
+
values and an arrow's expression body to the value flow, so a router a factory returns
|
|
747
|
+
(`httpRouter.use(await createRouter())`) is followed (#615).
|
|
748
|
+
- Backstage proxy: a TypeScript or JavaScript `fetch` whose URL starts with `/api/proxy/<endpoint>`
|
|
749
|
+
(also `discovery.getBaseUrl('proxy')` plus `/<endpoint>`) is a call to the `target` of that
|
|
750
|
+
endpoint in `proxy.endpoints` of an `app-config*.yaml`: a `${VAR}` target links through the
|
|
751
|
+
peer's `base_url_env` and a literal `http(s)://` target by host, the link's reason naming the
|
|
752
|
+
endpoint, and any other target leaves the call unlinked, which `meada status` says. A
|
|
753
|
+
`pathRewrite` that only strips the endpoint is followed; any other one, `ignorePath`,
|
|
754
|
+
`prependPath: false` and an endpoint the `app-config*.yaml` files disagree on leave the call
|
|
755
|
+
unlinked too (#616).
|
|
756
|
+
- Go: a struct field tagged `env:"X"` (cleanenv, caarlos0/env) or `envconfig:"X"`
|
|
757
|
+
(kelseyhightower/envconfig) is the environment read `X` where the field is read
|
|
758
|
+
(`cfg.API.URL`), so `base_url_env` links such a call as `inferred` instead of `ambiguous`
|
|
759
|
+
(#618).
|
|
760
|
+
|
|
761
|
+
- A Python pydantic-settings field is an environment read: a field `f` of a `BaseSettings`
|
|
762
|
+
subclass of the same file is the variable `<env_prefix><F>` (upper case), or its `alias` /
|
|
763
|
+
`validation_alias`, so the peer's `base_url_env` links `f"{settings.f}/orders"` as an
|
|
764
|
+
environment read does instead of leaving it `ambiguous`; other classes are unchanged (#619).
|
|
765
|
+
- A TypeScript or JavaScript base URL read through Backstage's `config.getString('a.b')` or
|
|
766
|
+
`getOptionalString('a.b')` is the variable `VAR` when an `app-config*.yaml` of the repository
|
|
767
|
+
holds `a.b: ${VAR}`, so the peer's `base_url_env` links the call as an environment read does
|
|
768
|
+
instead of leaving it `ambiguous`; a literal value or a key no file holds leaves the base
|
|
769
|
+
unresolved (#617).
|
|
770
|
+
- A PyPI version specifier is checked against the provider's version as PEP 440 says, as npm's
|
|
771
|
+
range is: `range mismatch` when the specifiers (`==`, `!=`, `<`, `<=`, `>`, `>=`, `~=`, `==X.*`
|
|
772
|
+
and `===`, joined by commas) reject the local version, nothing added when they accept it, and
|
|
773
|
+
`range unchecked` kept for a provider without a version and for a specifier it cannot read (a
|
|
774
|
+
Poetry `^1.2`, an unknown operator). A pre-release version is rejected unless a specifier
|
|
775
|
+
names one, and a mismatch removes no candidate (#534).
|
|
776
|
+
- A TypeScript or JavaScript `fetch` whose URL a function of the repository builds is a consumer:
|
|
777
|
+
a call to a function whose body is one returned string (an arrow function's expression body, or
|
|
778
|
+
a lone `return`) folds to it with the call's arguments, at the `fetch` and through a constant,
|
|
779
|
+
across imports. A part that does not fold, such as a base read from `process.env`, leaves the
|
|
780
|
+
consumer unresolved (#536).
|
|
781
|
+
- A Go `replace` by another module (`replace a => github.com/owner/repo`) keeps, among the providers
|
|
782
|
+
of the required module, the one in the workspace repository that path names, `exact`, for the
|
|
783
|
+
`require` and for the calls through its imports, instead of dropping the dependency; a
|
|
784
|
+
replacement no repository holds stays out (#532).
|
|
785
|
+
- A PyPI dependency with a uv source in `[tool.uv.sources]` links to the one package it names,
|
|
786
|
+
`exact`, for the entry and for the calls through its imports: `workspace = true` the member of
|
|
787
|
+
the consumer's uv workspace (`[tool.uv.workspace] members` less `exclude`), `path` the package
|
|
788
|
+
at that path, `git` the workspace repository of its URL; a `url` or `index` source stays out.
|
|
789
|
+
An entry without a uv source keeps linking to every package of its name (#533).
|
|
790
|
+
- The CLI messages (`--help`, `status`, `meada.toml` and index errors, and every other message of
|
|
791
|
+
the catalogs) are also in Spanish, selected when `LANG` starts with `es`; other values keep
|
|
792
|
+
falling back to English, and the MCP output stays English (#103).
|
|
793
|
+
- The workspaces profiles run the proposal server: `compose.proposals.yaml` and
|
|
794
|
+
`proposals.workspace.toml` in Compose (its own pull and volume, the read role, TLS on
|
|
795
|
+
`127.0.0.1:8445`) and an opt-in `proposals` block in the Helm chart (Deployment, Service,
|
|
796
|
+
bootstrap and probes with `timeoutSeconds`, absent by default); `scripts/compose-check` and
|
|
797
|
+
`scripts/helm-check` assert both. The identity provider recipes say how a person or an agent
|
|
798
|
+
gets a token whose `aud` is `[proposals] audience` (Entra ID, Okta, Keycloak, local accounts; Okta
|
|
799
|
+
needs a second authorization server the chart cannot render), in pt-BR, English and Spanish (#504).
|
|
800
|
+
- Over TLS, the Postgres client of the data layer authenticates with SCRAM channel binding
|
|
801
|
+
(`tls-server-end-point`, RFC 5929): it runs `SCRAM-SHA-256-PLUS` whenever the server offers
|
|
802
|
+
it, so a client that requires channel binding connects (#483). Loopback without TLS keeps plain
|
|
803
|
+
`SCRAM-SHA-256`.
|
|
804
|
+
- The console's named workspace view gains a versions page (#503): the versions newest first,
|
|
805
|
+
paged with the server's cursor; one version's entries, manifest text and diff against the
|
|
806
|
+
current one as the route answers; the history for operators and the administrator (a viewer
|
|
807
|
+
has no history control); and applying a listed version, which is a rollback when it was
|
|
808
|
+
current before, through the editor's confirmation at the base the page read. A stale base and
|
|
809
|
+
a refused entry show the server's message and the page reads the versions again. In pt-BR and
|
|
810
|
+
English.
|
|
811
|
+
- Gradle coordinate holes from `gradle.properties` and version catalogs (#467): a dependency
|
|
812
|
+
written `implementation(libs.models)` or with a `${name}` or `$name` the script leaves open
|
|
813
|
+
now links to the package providing its coordinate. `gradle.properties` of the repository root,
|
|
814
|
+
the settings file's directory and the module (the module's wins, and a name the script assigns
|
|
815
|
+
is never filled) feeds the same hole filler as the script's own declarations, and
|
|
816
|
+
`gradle/libs.versions.toml`, or a `*.versions.toml` a settings `from(files("..."))` names by a
|
|
817
|
+
relative path, maps `libs.<alias>` (dashes and underscores as dots) to `group:artifact` and
|
|
818
|
+
its version through `[libraries]` and `[versions]`; an alias the catalog lacks declares
|
|
819
|
+
nothing. Both files are bounded (`lang::MAX_BYTES`, 8192 entries) and have rows in the
|
|
820
|
+
manifest probes. `buildSrc`, convention plugins, included builds and build-time BOMs stay
|
|
821
|
+
unread. The stored manifest summary gains Gradle's `template` and catalog placeholders, so
|
|
822
|
+
existing indexes rebuild once (ADR 0004); the `conformance-java` export gained two links.
|
|
823
|
+
- Rust item macros in associated-item position and by `crate::` (#505, after #398): an
|
|
824
|
+
invocation of a qualifying item macro among the items of an `impl` or a trait gives its
|
|
825
|
+
body's methods, associated consts and types to that block, under the same rules (first arm
|
|
826
|
+
only, the attributes on the invocation, the same `cfg` handling), and `crate::m! { .. }`
|
|
827
|
+
qualifies as `m!` does; `other::m!`, `self::m!` and `super::m!` stay unread. `meada decide
|
|
828
|
+
--decider` now parses a file under the setting the index stored for it, so a function from an
|
|
829
|
+
item macro body is function-like and its span is sent.
|
|
830
|
+
- TypeScript and JavaScript: a `tsconfig.json` (or `jsconfig.json`) with `extends` naming a
|
|
831
|
+
relative path inside the repository takes the `paths` and `baseUrl` of the chain, the nearest
|
|
832
|
+
config that declares each option winning (#465), so the alias imports under a monorepo's
|
|
833
|
+
`packages/*` whose configs only extend the root's resolve. A package, a path outside the
|
|
834
|
+
repository, a chain of more than 8 configs after the nearest and a cycle are not followed (the
|
|
835
|
+
nearest config alone serves). Project `references` and a base not named `tsconfig.json` or
|
|
836
|
+
`jsconfig.json` are still not read.
|
|
837
|
+
|
|
838
|
+
### Fixed
|
|
839
|
+
|
|
840
|
+
- Go: a method named like a resty verb (`Get`, `Post`, `Put`, `Patch`, `Delete`, `Head`,
|
|
841
|
+
`Options`) called on a struct field that holds a repository, a Kubernetes client or a cache
|
|
842
|
+
client (`s.repo.Get(ctx, id)`) is no longer an HTTP consumer with an unresolved URL, so
|
|
843
|
+
`meada decide` lists no open item for it; a field holding a resty request or client keeps its
|
|
844
|
+
consumers (#621).
|
|
845
|
+
- A route whose handler sits in a test file (`*_test.go`, `*.test.*`, `*.spec.*`, `test_*.py`,
|
|
846
|
+
`*_test.py`, a `tests` or `__tests__` directory, `src/test`) is no provider: a test's router
|
|
847
|
+
or fake upstream no longer shows in `search` and the export, and no longer makes the client
|
|
848
|
+
repository a candidate for the route it consumes, so those calls link to the only real server
|
|
849
|
+
instead of turning `ambiguous`. The test code stays indexed; `test_routes = true` in
|
|
850
|
+
`meada.toml` keeps the routes as providers (#620).
|
|
851
|
+
- A comment inside a Go parameter list or argument list (`func NewRouter( //nolint:funlen`,
|
|
852
|
+
`NewRouter( // engine`) is no longer read as a parameter or an argument: it took position 0, so
|
|
853
|
+
a router handed to such a function reached none of its routes. The shared child walk of the
|
|
854
|
+
packs now skips comments, which also fixes the same shift in the TypeScript pack (#613).
|
|
855
|
+
|
|
856
|
+
- Express routes registered on an `express-promise-router` router (the Backstage backend default)
|
|
857
|
+
are provided: its default import counts as a router factory under any local name (#614).
|
|
858
|
+
- A refresh resolves a Swift file as a cold index does: the type parameters of a type or
|
|
859
|
+
function (`Page<Item>`) are kept in the index, so an `Item()` in an extension of `Page` in
|
|
860
|
+
another file is no construction of a type named `Item` after an edit to an unrelated Swift file
|
|
861
|
+
(the stored format changes, so an existing index is rebuilt once) (#609).
|
|
862
|
+
- A Kotlin `private` constructor, primary (`class C private constructor(..)`) or secondary, is
|
|
863
|
+
called only from inside its class: a call from another class no longer resolves to it, one from
|
|
864
|
+
the class, its companion or a nested class stays `exact`. `internal` is still not enforced
|
|
865
|
+
(#455).
|
|
866
|
+
- A Rust name two globs give (`use x::*; use y::*;`, which compiles only under `cfg`
|
|
867
|
+
alternatives) is `ambiguous` between them, not `exact` to the latest glob; an explicit item or
|
|
868
|
+
`use` beside the globs still wins (#439).
|
|
869
|
+
- A Swift parameter written as a name from outside the repository (`Ext.CompletionHandler`, which
|
|
870
|
+
may be an alias of a function type) neither takes nor refuses a trailing closure with certainty:
|
|
871
|
+
a call that fits an overload only through it is `ambiguous` among its overloads (`inferred` when
|
|
872
|
+
it is the only one), no longer `exact` to a sibling overload that reads as a function type or
|
|
873
|
+
absent. A parameter written as a type the repository declares or a standard value type still
|
|
874
|
+
refuses it (#456).
|
|
875
|
+
- TypeScript and JavaScript: `exports.y = function () {}` and `module.exports.y = ..` define the
|
|
876
|
+
symbol `exports.y` (exported as `y`), so a bare `y()` in the file no longer links to it and
|
|
877
|
+
`m.y()` through an import still does (#457).
|
|
878
|
+
- A PyPI package in the consumer's own repository that no uv source names links `inferred`, not
|
|
879
|
+
`exact`, when it is the one package of the name, with the reason "no uv source names the local
|
|
880
|
+
package, the registry package is the likely provider": pip and uv install the registry's
|
|
881
|
+
package, so a same-named stub (uv's `anyio_local`) is only a candidate. A source naming it
|
|
882
|
+
(`workspace = true`, `path`) and a single provider in another repository stay `exact` (#535).
|
|
883
|
+
- The `golden_diff` example exits with a message naming the range's refs and the `--range A...B`
|
|
884
|
+
flag when a merge-base cannot be found (a shallow or single-branch clone has no `origin/main`),
|
|
885
|
+
and with a usage error for `--range` without a value, instead of panicking (#592).
|
|
886
|
+
- `[postgres] schema` starting with `pg_` (reserved by Postgres) is refused at manifest read with
|
|
887
|
+
Meada's own message, in pt-BR and English, instead of Postgres's raw error at `meada postgres
|
|
888
|
+
migrate` (#482).
|
|
889
|
+
- The Helm node readiness probe sets `timeoutSeconds` (`readiness.timeoutSeconds`, default 8), so a
|
|
890
|
+
Postgres or Valkey that drops packets no longer exceeds the kubelet's 1 s default and marks every
|
|
891
|
+
node unready (#448).
|
|
892
|
+
- The container build copies every top-level `tests/fixtures/*.json` in the UI stage with one
|
|
893
|
+
`COPY`, so a UI test importing a new fixture no longer breaks the image (#495).
|
|
894
|
+
- The deploy fetch scripts (Compose `fetch-pulled.sh` and the chart `workspace.fetch`) read a
|
|
895
|
+
repositories manifest whose `repo` and `path` keys are written as quoted keys (`"repo" = ...`);
|
|
896
|
+
the shared awk program skipped them. Its test now takes the expected pairs of every case from the
|
|
897
|
+
`toml` crate instead of hand-written lists (#568).
|
|
898
|
+
- Rust: a `crate::a::*` glob written inside `a` or below it sees what `use super::*` sees,
|
|
899
|
+
the ancestor's private `use` included, so `Def::new()` through it is `exact` instead of
|
|
900
|
+
unresolved (#438). A glob of a sibling module still takes public names only.
|
|
901
|
+
|
|
902
|
+
### Changed
|
|
903
|
+
|
|
904
|
+
- An Express app or router a TypeScript or JavaScript function returns now takes the prefixes of
|
|
905
|
+
the mounts it is given to: `app.use('/v1', makeRouter())` serves `makeRouter`'s routes under
|
|
906
|
+
`/v1/...`, where they were served at the root, and the links of consumers of those paths change
|
|
907
|
+
with them (#615).
|
|
908
|
+
- A refresh keeps the rows of each group of language packs that resolve together (TypeScript and
|
|
909
|
+
JavaScript, Rust, Python, ...) when no file of the group changed and the config files,
|
|
910
|
+
manifests, file list and exports did not move: its contracts are not extracted again, its calls
|
|
911
|
+
are not resolved again and its files are not parsed again for their values. A one-line edit of
|
|
912
|
+
a Rust file of this repository refreshes in 3.3 s where it took 3.9 s (release build, median of
|
|
913
|
+
five); the export stays byte-identical to a cold one. A change of Meada's version re-extracts
|
|
914
|
+
every group once (#391).
|
|
915
|
+
- The console no longer creates the default account `admin` with a published password: without
|
|
916
|
+
`admin_password_env` or `admin_password_file`, the start that creates it generates the first
|
|
917
|
+
password, stores it with a change required, and prints it once on stderr (`accounts: default
|
|
918
|
+
account admin created; first password: ...`, right after the listening line; `docker compose
|
|
919
|
+
logs console` in the Compose recipe). No later start prints it; a lost one is recovered with
|
|
920
|
+
`meada ui reset-admin`. The password policy's `default_password` rule goes with the published
|
|
921
|
+
password, and ADR 0024 is amended (#579).
|
|
922
|
+
- The console asks `meada-core` through WebAssembly (`namedNameProblem`, `namedDescriptionProblem`,
|
|
923
|
+
`namedMessageProblem`, `resourceRoles`) whether a workspace name, description and version
|
|
924
|
+
message are valid and which resource roles exist, instead of keeping its own copy of the rule,
|
|
925
|
+
its bounds and the role list (#501). A version message is refused when empty by the same
|
|
926
|
+
function on the browser, the console API and `meada workspaces`: the empty-message refusal now
|
|
927
|
+
reads "a message is 1 to 500 characters, ..." instead of the request-body shape, and the
|
|
928
|
+
refusal of a too-long or control-bearing message reads "1 to 500" where it read "at most 500".
|
|
929
|
+
|
|
9
930
|
## [1.1.0] - 2026-11-02
|
|
10
931
|
|
|
11
932
|
A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
|
|
@@ -1080,7 +2001,9 @@ and `trace` from the two longest processes. The spec adds about 0.3 MB and 0.03
|
|
|
1080
2001
|
The rise of the single-file reindex since 2026-10-14 predates it (specs #22 and #23), and at
|
|
1081
2002
|
692 files it is close to its target.
|
|
1082
2003
|
|
|
1083
|
-
[Unreleased]: https://github.com/ClaudioMascaro/meada/compare/v1.
|
|
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
|
|
2006
|
+
[1.2.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.2.0
|
|
1084
2007
|
[1.1.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.1.0
|
|
1085
2008
|
[1.0.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.0.0
|
|
1086
2009
|
[0.1.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v0.1.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.
|
|
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.
|
|
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.
|
|
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).
|
|
@@ -111,7 +111,7 @@ Meada 1.0 entrega todo o escopo da v1 do [ADR 0003](docs/adr/0003-v1-scope-and-r
|
|
|
111
111
|
- **Níveis**: um nível em cada ligação, cadeias que atravessam repositórios e decisões com
|
|
112
112
|
decisor opcional (`meada decide`).
|
|
113
113
|
- **Análises**: drift de forma, comunidades e processos.
|
|
114
|
-
- **Linguagens no 1.0**: nove
|
|
114
|
+
- **Linguagens no 1.0**: nove: TypeScript, JavaScript, Python, Go, Rust, Java, Kotlin, C# e
|
|
115
115
|
Swift (#26 a #29, ADR 0003).
|
|
116
116
|
|
|
117
117
|
**Promessa de estabilidade.** A partir do 1.0 vale o semver: uma mudança incompatível em um
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"hasInstallScript": true,
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"name": "@meada/meada",
|
|
22
|
-
"version": "1.
|
|
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.
|
|
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.
|
|
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.
|
|
92
|
+
"version": "1.3.0",
|
|
93
93
|
"volta": {
|
|
94
94
|
"node": "18.14.1",
|
|
95
95
|
"npm": "9.5.0"
|