@meada/meada 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,223 @@ All notable changes to Meada are recorded here. The format follows
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.2.0] - 2026-11-04
10
+
11
+ A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
12
+ package reading (PEP 440 specifiers, uv sources, Go `replace` by a held module, `fetch` URLs a
13
+ function builds), resolution in the Rust, TypeScript and Gradle packs, the console's versions
14
+ page for a named workspace, the proposal server in the Compose and Helm recipes, SCRAM channel
15
+ binding to Postgres, CLI messages in Spanish, a generated first password for the console's
16
+ default `admin` account instead of a published one (#579), a refresh that keeps the language
17
+ 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
18
+ manifest summary changes, so existing indexes are rebuilt once on first use. `meada-core` 1.2.0 deprecates `msg::pt()` in
19
+ favour of `msg::lang()` (`msg::lang() == msg::Lang::Pt`), types `effective::Diagnostic::code` as
20
+ `DiagnosticCode` (the JSON is unchanged) and makes `named::message_problem("")` return `Some`;
21
+ the new `msg::Lang` and `effective::DiagnosticCode` are `#[non_exhaustive]`, so a match on
22
+ either needs a wildcard arm. A crate that declares `meada-core = "1.1"` meets the last two
23
+ changes on `cargo update`, and `=1.1.0` stays on the old API. The tree, the `meada-core` pin, the
24
+ Dockerfile, the compose defaults and the Helm chart declare `1.2.0`, and the `v1.2.0` tag goes
25
+ on the `release/1.2` branch, cut from this entry's merge on main. Publication
26
+ (crates, the staged npm package, the GitHub draft release) belongs to the maintainer.
27
+ Release notes are available in
28
+ [pt-BR](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.2.0.md),
29
+ [English](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.2.0.en.md) and
30
+ [Spanish](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.2.0.es.md).
31
+
32
+ ### Added
33
+
34
+ - Backstage backends: the router a backend plugin gives its `httpRouter`
35
+ (`coreServices.httpRouter`) is served under `/api/<pluginId>` when `createBackendPlugin` writes
36
+ its `pluginId` as a literal or as a `const` of the file bound to one, so two plugins with the
37
+ same relative path no longer collide, and a URL
38
+ that starts with `discovery.getBaseUrl('<id>')` (held by a constant or written in place) starts
39
+ at `/api/<id>`, its link's reason naming the plugin's mount (as does a hostless call of a route
40
+ the plugin serves in its own repository). A plugin whose `pluginId` cannot be read stays at the
41
+ root, and `meada status` names it. TypeScript and JavaScript functions now give their `return`
42
+ values and an arrow's expression body to the value flow, so a router a factory returns
43
+ (`httpRouter.use(await createRouter())`) is followed (#615).
44
+ - Backstage proxy: a TypeScript or JavaScript `fetch` whose URL starts with `/api/proxy/<endpoint>`
45
+ (also `discovery.getBaseUrl('proxy')` plus `/<endpoint>`) is a call to the `target` of that
46
+ endpoint in `proxy.endpoints` of an `app-config*.yaml`: a `${VAR}` target links through the
47
+ peer's `base_url_env` and a literal `http(s)://` target by host, the link's reason naming the
48
+ endpoint, and any other target leaves the call unlinked, which `meada status` says. A
49
+ `pathRewrite` that only strips the endpoint is followed; any other one, `ignorePath`,
50
+ `prependPath: false` and an endpoint the `app-config*.yaml` files disagree on leave the call
51
+ unlinked too (#616).
52
+ - Go: a struct field tagged `env:"X"` (cleanenv, caarlos0/env) or `envconfig:"X"`
53
+ (kelseyhightower/envconfig) is the environment read `X` where the field is read
54
+ (`cfg.API.URL`), so `base_url_env` links such a call as `inferred` instead of `ambiguous`
55
+ (#618).
56
+
57
+ - A Python pydantic-settings field is an environment read: a field `f` of a `BaseSettings`
58
+ subclass of the same file is the variable `<env_prefix><F>` (upper case), or its `alias` /
59
+ `validation_alias`, so the peer's `base_url_env` links `f"{settings.f}/orders"` as an
60
+ environment read does instead of leaving it `ambiguous`; other classes are unchanged (#619).
61
+ - A TypeScript or JavaScript base URL read through Backstage's `config.getString('a.b')` or
62
+ `getOptionalString('a.b')` is the variable `VAR` when an `app-config*.yaml` of the repository
63
+ holds `a.b: ${VAR}`, so the peer's `base_url_env` links the call as an environment read does
64
+ instead of leaving it `ambiguous`; a literal value or a key no file holds leaves the base
65
+ unresolved (#617).
66
+ - A PyPI version specifier is checked against the provider's version as PEP 440 says, as npm's
67
+ range is: `range mismatch` when the specifiers (`==`, `!=`, `<`, `<=`, `>`, `>=`, `~=`, `==X.*`
68
+ and `===`, joined by commas) reject the local version, nothing added when they accept it, and
69
+ `range unchecked` kept for a provider without a version and for a specifier it cannot read (a
70
+ Poetry `^1.2`, an unknown operator). A pre-release version is rejected unless a specifier
71
+ names one, and a mismatch removes no candidate (#534).
72
+ - A TypeScript or JavaScript `fetch` whose URL a function of the repository builds is a consumer:
73
+ a call to a function whose body is one returned string (an arrow function's expression body, or
74
+ a lone `return`) folds to it with the call's arguments, at the `fetch` and through a constant,
75
+ across imports. A part that does not fold, such as a base read from `process.env`, leaves the
76
+ consumer unresolved (#536).
77
+ - A Go `replace` by another module (`replace a => github.com/owner/repo`) keeps, among the providers
78
+ of the required module, the one in the workspace repository that path names, `exact`, for the
79
+ `require` and for the calls through its imports, instead of dropping the dependency; a
80
+ replacement no repository holds stays out (#532).
81
+ - A PyPI dependency with a uv source in `[tool.uv.sources]` links to the one package it names,
82
+ `exact`, for the entry and for the calls through its imports: `workspace = true` the member of
83
+ the consumer's uv workspace (`[tool.uv.workspace] members` less `exclude`), `path` the package
84
+ at that path, `git` the workspace repository of its URL; a `url` or `index` source stays out.
85
+ An entry without a uv source keeps linking to every package of its name (#533).
86
+ - The CLI messages (`--help`, `status`, `meada.toml` and index errors, and every other message of
87
+ the catalogs) are also in Spanish, selected when `LANG` starts with `es`; other values keep
88
+ falling back to English, and the MCP output stays English (#103).
89
+ - The workspaces profiles run the proposal server: `compose.proposals.yaml` and
90
+ `proposals.workspace.toml` in Compose (its own pull and volume, the read role, TLS on
91
+ `127.0.0.1:8445`) and an opt-in `proposals` block in the Helm chart (Deployment, Service,
92
+ bootstrap and probes with `timeoutSeconds`, absent by default); `scripts/compose-check` and
93
+ `scripts/helm-check` assert both. The identity provider recipes say how a person or an agent
94
+ gets a token whose `aud` is `[proposals] audience` (Entra ID, Okta, Keycloak, local accounts; Okta
95
+ needs a second authorization server the chart cannot render), in pt-BR, English and Spanish (#504).
96
+ - Over TLS, the Postgres client of the data layer authenticates with SCRAM channel binding
97
+ (`tls-server-end-point`, RFC 5929): it runs `SCRAM-SHA-256-PLUS` whenever the server offers
98
+ it, so a client that requires channel binding connects (#483). Loopback without TLS keeps plain
99
+ `SCRAM-SHA-256`.
100
+ - The console's named workspace view gains a versions page (#503): the versions newest first,
101
+ paged with the server's cursor; one version's entries, manifest text and diff against the
102
+ current one as the route answers; the history for operators and the administrator (a viewer
103
+ has no history control); and applying a listed version, which is a rollback when it was
104
+ current before, through the editor's confirmation at the base the page read. A stale base and
105
+ a refused entry show the server's message and the page reads the versions again. In pt-BR and
106
+ English.
107
+ - Gradle coordinate holes from `gradle.properties` and version catalogs (#467): a dependency
108
+ written `implementation(libs.models)` or with a `${name}` or `$name` the script leaves open
109
+ now links to the package providing its coordinate. `gradle.properties` of the repository root,
110
+ the settings file's directory and the module (the module's wins, and a name the script assigns
111
+ is never filled) feeds the same hole filler as the script's own declarations, and
112
+ `gradle/libs.versions.toml`, or a `*.versions.toml` a settings `from(files("..."))` names by a
113
+ relative path, maps `libs.<alias>` (dashes and underscores as dots) to `group:artifact` and
114
+ its version through `[libraries]` and `[versions]`; an alias the catalog lacks declares
115
+ nothing. Both files are bounded (`lang::MAX_BYTES`, 8192 entries) and have rows in the
116
+ manifest probes. `buildSrc`, convention plugins, included builds and build-time BOMs stay
117
+ unread. The stored manifest summary gains Gradle's `template` and catalog placeholders, so
118
+ existing indexes rebuild once (ADR 0004); the `conformance-java` export gained two links.
119
+ - Rust item macros in associated-item position and by `crate::` (#505, after #398): an
120
+ invocation of a qualifying item macro among the items of an `impl` or a trait gives its
121
+ body's methods, associated consts and types to that block, under the same rules (first arm
122
+ only, the attributes on the invocation, the same `cfg` handling), and `crate::m! { .. }`
123
+ qualifies as `m!` does; `other::m!`, `self::m!` and `super::m!` stay unread. `meada decide
124
+ --decider` now parses a file under the setting the index stored for it, so a function from an
125
+ item macro body is function-like and its span is sent.
126
+ - TypeScript and JavaScript: a `tsconfig.json` (or `jsconfig.json`) with `extends` naming a
127
+ relative path inside the repository takes the `paths` and `baseUrl` of the chain, the nearest
128
+ config that declares each option winning (#465), so the alias imports under a monorepo's
129
+ `packages/*` whose configs only extend the root's resolve. A package, a path outside the
130
+ repository, a chain of more than 8 configs after the nearest and a cycle are not followed (the
131
+ nearest config alone serves). Project `references` and a base not named `tsconfig.json` or
132
+ `jsconfig.json` are still not read.
133
+
134
+ ### Fixed
135
+
136
+ - Go: a method named like a resty verb (`Get`, `Post`, `Put`, `Patch`, `Delete`, `Head`,
137
+ `Options`) called on a struct field that holds a repository, a Kubernetes client or a cache
138
+ client (`s.repo.Get(ctx, id)`) is no longer an HTTP consumer with an unresolved URL, so
139
+ `meada decide` lists no open item for it; a field holding a resty request or client keeps its
140
+ consumers (#621).
141
+ - A route whose handler sits in a test file (`*_test.go`, `*.test.*`, `*.spec.*`, `test_*.py`,
142
+ `*_test.py`, a `tests` or `__tests__` directory, `src/test`) is no provider: a test's router
143
+ or fake upstream no longer shows in `search` and the export, and no longer makes the client
144
+ repository a candidate for the route it consumes, so those calls link to the only real server
145
+ instead of turning `ambiguous`. The test code stays indexed; `test_routes = true` in
146
+ `meada.toml` keeps the routes as providers (#620).
147
+ - A comment inside a Go parameter list or argument list (`func NewRouter( //nolint:funlen`,
148
+ `NewRouter( // engine`) is no longer read as a parameter or an argument: it took position 0, so
149
+ a router handed to such a function reached none of its routes. The shared child walk of the
150
+ packs now skips comments, which also fixes the same shift in the TypeScript pack (#613).
151
+
152
+ - Express routes registered on an `express-promise-router` router (the Backstage backend default)
153
+ are provided: its default import counts as a router factory under any local name (#614).
154
+ - A refresh resolves a Swift file as a cold index does: the type parameters of a type or
155
+ function (`Page<Item>`) are kept in the index, so an `Item()` in an extension of `Page` in
156
+ another file is no construction of a type named `Item` after an edit to an unrelated Swift file
157
+ (the stored format changes, so an existing index is rebuilt once) (#609).
158
+ - A Kotlin `private` constructor, primary (`class C private constructor(..)`) or secondary, is
159
+ called only from inside its class: a call from another class no longer resolves to it, one from
160
+ the class, its companion or a nested class stays `exact`. `internal` is still not enforced
161
+ (#455).
162
+ - A Rust name two globs give (`use x::*; use y::*;`, which compiles only under `cfg`
163
+ alternatives) is `ambiguous` between them, not `exact` to the latest glob; an explicit item or
164
+ `use` beside the globs still wins (#439).
165
+ - A Swift parameter written as a name from outside the repository (`Ext.CompletionHandler`, which
166
+ may be an alias of a function type) neither takes nor refuses a trailing closure with certainty:
167
+ a call that fits an overload only through it is `ambiguous` among its overloads (`inferred` when
168
+ it is the only one), no longer `exact` to a sibling overload that reads as a function type or
169
+ absent. A parameter written as a type the repository declares or a standard value type still
170
+ refuses it (#456).
171
+ - TypeScript and JavaScript: `exports.y = function () {}` and `module.exports.y = ..` define the
172
+ symbol `exports.y` (exported as `y`), so a bare `y()` in the file no longer links to it and
173
+ `m.y()` through an import still does (#457).
174
+ - A PyPI package in the consumer's own repository that no uv source names links `inferred`, not
175
+ `exact`, when it is the one package of the name, with the reason "no uv source names the local
176
+ package, the registry package is the likely provider": pip and uv install the registry's
177
+ package, so a same-named stub (uv's `anyio_local`) is only a candidate. A source naming it
178
+ (`workspace = true`, `path`) and a single provider in another repository stay `exact` (#535).
179
+ - The `golden_diff` example exits with a message naming the range's refs and the `--range A...B`
180
+ flag when a merge-base cannot be found (a shallow or single-branch clone has no `origin/main`),
181
+ and with a usage error for `--range` without a value, instead of panicking (#592).
182
+ - `[postgres] schema` starting with `pg_` (reserved by Postgres) is refused at manifest read with
183
+ Meada's own message, in pt-BR and English, instead of Postgres's raw error at `meada postgres
184
+ migrate` (#482).
185
+ - The Helm node readiness probe sets `timeoutSeconds` (`readiness.timeoutSeconds`, default 8), so a
186
+ Postgres or Valkey that drops packets no longer exceeds the kubelet's 1 s default and marks every
187
+ node unready (#448).
188
+ - The container build copies every top-level `tests/fixtures/*.json` in the UI stage with one
189
+ `COPY`, so a UI test importing a new fixture no longer breaks the image (#495).
190
+ - The deploy fetch scripts (Compose `fetch-pulled.sh` and the chart `workspace.fetch`) read a
191
+ repositories manifest whose `repo` and `path` keys are written as quoted keys (`"repo" = ...`);
192
+ the shared awk program skipped them. Its test now takes the expected pairs of every case from the
193
+ `toml` crate instead of hand-written lists (#568).
194
+ - Rust: a `crate::a::*` glob written inside `a` or below it sees what `use super::*` sees,
195
+ the ancestor's private `use` included, so `Def::new()` through it is `exact` instead of
196
+ unresolved (#438). A glob of a sibling module still takes public names only.
197
+
198
+ ### Changed
199
+
200
+ - An Express app or router a TypeScript or JavaScript function returns now takes the prefixes of
201
+ the mounts it is given to: `app.use('/v1', makeRouter())` serves `makeRouter`'s routes under
202
+ `/v1/...`, where they were served at the root, and the links of consumers of those paths change
203
+ with them (#615).
204
+ - A refresh keeps the rows of each group of language packs that resolve together (TypeScript and
205
+ JavaScript, Rust, Python, ...) when no file of the group changed and the config files,
206
+ manifests, file list and exports did not move: its contracts are not extracted again, its calls
207
+ are not resolved again and its files are not parsed again for their values. A one-line edit of
208
+ a Rust file of this repository refreshes in 3.3 s where it took 3.9 s (release build, median of
209
+ five); the export stays byte-identical to a cold one. A change of Meada's version re-extracts
210
+ every group once (#391).
211
+ - The console no longer creates the default account `admin` with a published password: without
212
+ `admin_password_env` or `admin_password_file`, the start that creates it generates the first
213
+ password, stores it with a change required, and prints it once on stderr (`accounts: default
214
+ account admin created; first password: ...`, right after the listening line; `docker compose
215
+ logs console` in the Compose recipe). No later start prints it; a lost one is recovered with
216
+ `meada ui reset-admin`. The password policy's `default_password` rule goes with the published
217
+ password, and ADR 0024 is amended (#579).
218
+ - The console asks `meada-core` through WebAssembly (`namedNameProblem`, `namedDescriptionProblem`,
219
+ `namedMessageProblem`, `resourceRoles`) whether a workspace name, description and version
220
+ message are valid and which resource roles exist, instead of keeping its own copy of the rule,
221
+ its bounds and the role list (#501). A version message is refused when empty by the same
222
+ function on the browser, the console API and `meada workspaces`: the empty-message refusal now
223
+ reads "a message is 1 to 500 characters, ..." instead of the request-body shape, and the
224
+ refusal of a too-long or control-bearing message reads "1 to 500" where it read "at most 500".
225
+
9
226
  ## [1.1.0] - 2026-11-02
10
227
 
11
228
  A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
@@ -1080,7 +1297,8 @@ and `trace` from the two longest processes. The spec adds about 0.3 MB and 0.03
1080
1297
  The rise of the single-file reindex since 2026-10-14 predates it (specs #22 and #23), and at
1081
1298
  692 files it is close to its target.
1082
1299
 
1083
- [Unreleased]: https://github.com/ClaudioMascaro/meada/compare/v1.1.0...HEAD
1300
+ [Unreleased]: https://github.com/ClaudioMascaro/meada/compare/v1.2.0...HEAD
1301
+ [1.2.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.2.0
1084
1302
  [1.1.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.1.0
1085
1303
  [1.0.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.0.0
1086
1304
  [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.1.0` | a linha `docker run` em [Conectar um agente](#conectar-um-agente-mcp) |
21
+ | Docker | `docker pull ghcr.io/claudiomascaro/meada:1.2.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.1.0 mcp"]
78
+ "args": ["-c", "exec docker run -i --rm --network none --user \"$(id -u):$(id -g)\" -v \"${PWD%/*}:${PWD%/*}\" -w \"$PWD\" ghcr.io/claudiomascaro/meada:1.2.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.1.0/skills/meada/SKILL.md -o ~/.claude/skills/meada/SKILL.md
100
+ curl -fsSL https://raw.githubusercontent.com/ClaudioMascaro/meada/v1.2.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, TypeScript, JavaScript, Python, Go, Rust, Java, Kotlin, C# e
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
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "Apache-2.0",
21
21
  "name": "@meada/meada",
22
- "version": "1.1.0"
22
+ "version": "1.2.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.1.0"
51
+ "version": "1.2.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.1.0"
3
+ "https://github.com/ClaudioMascaro/meada/releases/download/v1.2.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.1.0",
92
+ "version": "1.2.0",
93
93
  "volta": {
94
94
  "node": "18.14.1",
95
95
  "npm": "9.5.0"