@meada/meada 0.1.0 → 1.1.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 +528 -1
- package/README.md +120 -3
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,531 @@ All notable changes to Meada are recorded here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.1.0] - 2026-11-02
|
|
10
|
+
|
|
11
|
+
A minor release on the [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md):
|
|
12
|
+
local accounts (ADR 0024) in the console, the proposal server and the nodes, carried by the
|
|
13
|
+
`cloud` image, the Compose recipe and the Helm chart; the export's `format` and indexed commit;
|
|
14
|
+
client-side deadlines on every Postgres call; durable pulled-generation writes; resolver fixes
|
|
15
|
+
for C#, Kotlin, Rust and Swift (tier b3); and the fixes of tiers b1 and b2. The index schema
|
|
16
|
+
version changes, so existing indexes are rebuilt once on first use. `meada-core` 1.1.0 adds `format`, `commit` and `dirty` to `Export`, and its
|
|
17
|
+
`export::parse` refuses a document without `format`: re-export with 1.1.0 before parsing an export
|
|
18
|
+
written by 1.0.0. The tree, the `meada-core` pin, the Dockerfile, the compose defaults and the
|
|
19
|
+
Helm chart declare `1.1.0`, and the `v1.1.0` tag follows this entry's merge on main. Publication
|
|
20
|
+
(crates, the staged npm package, the GitHub draft release) belongs to the maintainer.
|
|
21
|
+
Release notes are available in
|
|
22
|
+
[pt-BR](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.1.0.md),
|
|
23
|
+
[English](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.1.0.en.md) and
|
|
24
|
+
[Spanish](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.1.0.es.md).
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- The export format and the indexed commit (#512, ADR 0004 "Canonical export"): every export
|
|
29
|
+
starts with `format` (`meada_core::export::FORMAT`, 1), which rises only when a reader of the
|
|
30
|
+
previous shape would misread the new one, never for an added optional field; then
|
|
31
|
+
`repository`, then `commit` and `dirty`, both optional and left out together. Locally `meada export` reads `HEAD` before and
|
|
32
|
+
after its refresh and the checkout's status after it (ignored files, `.meada/` among them, do
|
|
33
|
+
not count), and names the commit only when `HEAD` did not move and the index is fresh; outside
|
|
34
|
+
git or before the first commit both are left out. In server mode they come from the commit
|
|
35
|
+
`meada index --workspace` recorded beside the index, or a generation's `head`, never from the
|
|
36
|
+
mirror's live `HEAD`, with `dirty` false. For `meada-core` crate users: `Export` gains
|
|
37
|
+
`format`, `commit` and `dirty` (a minor change, the struct being `#[non_exhaustive]`, so the
|
|
38
|
+
next `meada-core` release is 1.1.0), and `export::parse` refuses a document without `format`,
|
|
39
|
+
naming the field, so an export written before this release no longer parses. Every `*.export.json` golden gained the three fields.
|
|
40
|
+
|
|
41
|
+
- Named workspaces and the proposal server with local accounts (#562, ADR 0024, from #551):
|
|
42
|
+
`[catalog]` and `[workspaces]` (and so `[proposals]`) accept `[accounts.github]` in place of
|
|
43
|
+
`[oidc.github]` and still need one of the two (`[catalog] needs [oidc.github] or
|
|
44
|
+
[accounts.github]`; `[workspaces]` now names `[ui]` and `[catalog]`, the catalog naming the
|
|
45
|
+
provider). Eligibility reads the account's verified login, an operator account is the platform
|
|
46
|
+
administrator, and workspace operator lists, version authors, history and audit records name
|
|
47
|
+
`local:` subjects. `POST /api/v1/account/tokens` takes `{"surface": "proposals"}` when the
|
|
48
|
+
console's bootstrap has `[proposals]` (audience `meada:proposals`; a 422 `invalid_surface`
|
|
49
|
+
without it), `config` carries `"proposals": true` and the profile page offers the surface. The
|
|
50
|
+
proposal server with `[accounts]` and no `[oidc]` reads the public key at start and admits only
|
|
51
|
+
those tokens (a session token or a node's agent token is a 401 with `WWW-Authenticate: Bearer`,
|
|
52
|
+
no protected resource metadata), deriving the subject, login, groups, grant and role from the
|
|
53
|
+
token alone. No golden changed.
|
|
54
|
+
- The verified GitHub login of local accounts (#561, ADR 0024, from #551): `[accounts.github]`
|
|
55
|
+
(`host`, `roles`, `max_age_seconds` as `[oidc.github]`, plus `api`, `https://api.github.com` by
|
|
56
|
+
default on `github.com` and required on any other host) is the GitHub grant provider of local
|
|
57
|
+
accounts. A person pastes a GitHub personal access token on their profile page or sends it to
|
|
58
|
+
`POST /api/v1/account/github`; the console calls `GET /user` on `api` once, keeps the lowercase
|
|
59
|
+
login and drops the token, and answers a fresh session token carrying the login. A login
|
|
60
|
+
another account holds is a 409 `login_taken`, GitHub's refusal a 422, GitHub out of reach a
|
|
61
|
+
503. `POST /api/v1/account/github/remove` and the accounts page's `remove_github` action remove
|
|
62
|
+
it. Session and agent tokens carry the verified login, so the GitHub grant joins the groups
|
|
63
|
+
grant in the console (`session` shows `login`, `github_host` and `github_grant`), on nodes, in
|
|
64
|
+
a team operator's additions (`added_by`), in the audit's `login` column and in the exclusions
|
|
65
|
+
marks; `meada github-app roles` reads `[accounts.github]`. Recorded `account.github` and
|
|
66
|
+
`account.remove_github`; the personal access token is never stored, logged or audited. No
|
|
67
|
+
golden changed.
|
|
68
|
+
|
|
69
|
+
- Helm chart support for local accounts (#565, ADR 0024, from #551): `modules.accounts` renders
|
|
70
|
+
`[accounts]` from values, with `values-accounts.yaml` as the proof-of-concept shape (a writable
|
|
71
|
+
console with `operations = true`, Postgres and no identity provider). The Ed25519 private key
|
|
72
|
+
comes from its own Secret and is mounted only in the console's `console` container, the public
|
|
73
|
+
key from another Secret in the console and the nodes (a node also gets `[ui] public_url`, the
|
|
74
|
+
token issuer, and `[postgres]`), the initial admin password from an optional Secret in the
|
|
75
|
+
console. `modules.accounts.groups` and `modules.accounts.github` carry `[accounts.groups]` and
|
|
76
|
+
`[accounts.github]` (the refresh job, with `modules.githubApp`, gets the GitHub grant provider and runs the role check, and
|
|
77
|
+
`modules.workspaces` accepts it in place of `modules.oidc.github`); `modules.accounts.breakGlass`
|
|
78
|
+
keeps `[accounts]` in the console alone beside `modules.oidc`. The chart refuses a missing
|
|
79
|
+
Postgres or console, equal key Secrets, accounts beside OIDC without break glass, and groups or
|
|
80
|
+
GitHub under break glass. `scripts/helm-check` covers the sections, the mounts and the refusals;
|
|
81
|
+
the chart READMEs (pt-BR, English, Spanish) no longer say a writable console needs OIDC. The
|
|
82
|
+
proposal server is not part of the chart. `[accounts.github]` renders as the spec names it and
|
|
83
|
+
is parsed once #561 lands. No golden changed.
|
|
84
|
+
|
|
85
|
+
- One-command proof of concept in the Compose recipe (#564, ADR 0024, from #551):
|
|
86
|
+
`cp .env.accounts.example .env && docker compose up -d` starts the generations fleet, Valkey,
|
|
87
|
+
the store, Postgres with its migration, a writable console with local accounts and nodes that
|
|
88
|
+
admit agent tokens. `compose.accounts.yaml` adds the Ed25519 key pair (made once by the
|
|
89
|
+
`certificates` step, never printed, the private key mounted read-only in the console alone and
|
|
90
|
+
the public one in the nodes), the console's and the nodes' `[accounts]` manifests, a one-shot
|
|
91
|
+
`seed` of the first workspace version (only while the store has none) and a node proxy that
|
|
92
|
+
forwards `Authorization` with no static bearer. The other profiles are unchanged, and
|
|
93
|
+
`scripts/compose-check` covers the new one. The Compose README (pt, en, es) starts with it and
|
|
94
|
+
covers `MEADA_ADMIN_PASSWORD`, `meada ui reset-admin`, key rotation and rate limiting the
|
|
95
|
+
sign-in route at the proxy.
|
|
96
|
+
|
|
97
|
+
- Agent tokens for the nodes (#560, ADR 0024, from #551): a signed-in local account generates,
|
|
98
|
+
on its profile page or through `POST /api/v1/account/tokens` (`{surface: "nodes", hours}`, 1 to
|
|
99
|
+
168 hours, 8 by default), an agent token shown once (`{token, expires_at, surface}`), signed
|
|
100
|
+
with the account's role and groups as its row stands and a random token id, recorded
|
|
101
|
+
`account.token` (surface, hours, token id, never the token). A change-required account gets the
|
|
102
|
+
403 `password_change_required`, a suspended one the role refusal; the console answers an agent
|
|
103
|
+
token with 401. A node with `[accounts]` and no `[oidc]` (`meada mcp --listen`) now reads the
|
|
104
|
+
signing public key at start, and the console's `[ui] public_url` from a `[ui]` section its
|
|
105
|
+
manifest must carry, refusing to start without either; it admits only agent tokens for the
|
|
106
|
+
nodes (a 401 `Bearer` before routing for any other, a session token included) and answers
|
|
107
|
+
under the grant `[accounts.groups]` gives their groups (every repository without the table),
|
|
108
|
+
as an identity provider's token is answered. The `accounts` feature now implies `ui`. No golden
|
|
109
|
+
changed.
|
|
110
|
+
|
|
111
|
+
- Accounts page in the console (#559, ADR 0024, from #551): the global operator of a console with
|
|
112
|
+
local accounts gets `/accounts`, listing every account (role, groups, state with a suspended
|
|
113
|
+
account marked and a locked one saying until when, change required, last password change), a
|
|
114
|
+
create form (username pattern and password length checked first, "change on first sign-in"
|
|
115
|
+
checked by default) and, per account, role, groups, suspend, reactivate and reset password,
|
|
116
|
+
each behind the shared confirmation dialog with the server's refusals (`last_operator` and the
|
|
117
|
+
rest) shown unchanged. Any other role, and a console under break glass, gets the not-found
|
|
118
|
+
page at that path. The audit page names every `account.*` action in Portuguese and English.
|
|
119
|
+
The password rule `common_password` now has its own copy. Front end only, no golden changed.
|
|
120
|
+
|
|
121
|
+
- Groups of local accounts (#558, ADR 0024, from #551): the global operator gives accounts groups
|
|
122
|
+
(`groups` on `POST /api/v1/accounts`, and the `groups` action of
|
|
123
|
+
`POST /api/v1/accounts/<username>`, each an owner name, else a 422 `invalid_group`);
|
|
124
|
+
`GET /api/v1/accounts` lists them, and each change is recorded `account.groups`.
|
|
125
|
+
`[accounts.groups]` maps groups to identities as `[oidc.groups]` does: once it exists, a local
|
|
126
|
+
session's grant is what its groups map to, and it bounds every view (the manifest, the
|
|
127
|
+
workspace and its versions, the store, the repositories, the credentials, the playground, the
|
|
128
|
+
exports and the graph views) as an identity provider's grant does; without it every local
|
|
129
|
+
account still reads every repository. A local viewer whose group owns an entry of the current
|
|
130
|
+
workspace version its grant reads is a team operator (ADR 0015). Session tokens carry the
|
|
131
|
+
groups, so a change reaches reads at the next sign-in and writes at once (the account row is
|
|
132
|
+
read before each). `GET /api/v1/admission` with `[accounts]` now answers: `accounts` (the mode,
|
|
133
|
+
`accounts` or `break_glass`, and the signing public key's fingerprint, `blake3:` and the hex
|
|
134
|
+
BLAKE3 hash of the raw Ed25519 key) and, without `[oidc]`, the groups table bounded by the
|
|
135
|
+
caller's grant. No golden changed.
|
|
136
|
+
|
|
137
|
+
- Account administration for local accounts (#557, ADR 0024, from #551): the global operator
|
|
138
|
+
lists every account (`GET /api/v1/accounts`: username, role, state, the end of a lock, change
|
|
139
|
+
required, last password change, created and created by, never a hash), creates one
|
|
140
|
+
(`POST /api/v1/accounts`, `{username, role, password, change_required}`, the policy applied to
|
|
141
|
+
the temporary password, a change required unless the body turns it off; a malformed username a
|
|
142
|
+
422 `invalid_username`, a taken one a 409 `username_taken`) and changes one
|
|
143
|
+
(`POST /api/v1/accounts/<username>`, one `action`: `role`, `suspend`, `reactivate` or
|
|
144
|
+
`reset_password`, which clears a lock and requires a change unless told not to; an unknown
|
|
145
|
+
account a 404). Suspending or demoting the last active operator is a 409 `last_operator`,
|
|
146
|
+
decided under the schema's advisory lock so two requests at once never leave none. Anyone else
|
|
147
|
+
gets a 403. The routes answer whatever `[ui] operations` says; workspace and generation writes
|
|
148
|
+
keep requiring it. Every console write of a local account now reads the account's row first,
|
|
149
|
+
so a suspended or demoted account loses its writes at once, while its reads last until its
|
|
150
|
+
token expires. Audit actions `account.create`, `account.role`, `account.suspend`,
|
|
151
|
+
`account.reactivate` and `account.reset_password` name the account and the fields changed,
|
|
152
|
+
never a password, written before the change (503 `audit_unavailable` otherwise); `account` is
|
|
153
|
+
the route-level action of a change refused before its body is read. No route deletes or
|
|
154
|
+
renames an account; under `[accounts] break_glass` (#563) none of these routes exists, each a
|
|
155
|
+
404. No golden changed.
|
|
156
|
+
|
|
157
|
+
- Break-glass account beside the identity provider (#563, ADR 0024, from #551): `[accounts]
|
|
158
|
+
break_glass = true` lets the section sit beside `[oidc]`; without `[oidc]` it is an error, and
|
|
159
|
+
`[accounts.groups]` or `[accounts.github]` under it is an error naming the table. The console
|
|
160
|
+
then signs in only the default account (any other username gets the wrong password's 401,
|
|
161
|
+
audited `not_break_glass`, the table never read) as the global operator, and admits its session
|
|
162
|
+
token beside the identity provider's, each bearer routed by its issuer to one verifier, so the
|
|
163
|
+
identity provider's keys never check a console token and the signing key never checks an
|
|
164
|
+
identity provider's; a console whose `[oidc] issuer` is its own `public_url` refuses to start.
|
|
165
|
+
The password change works; no other route of local accounts exists. Nodes and the proposal
|
|
166
|
+
server keep admitting only the identity provider and read no key. `config` adds `break_glass:
|
|
167
|
+
true`, and the front end offers a discreet break-glass sign-in (`/break-glass`) beside the
|
|
168
|
+
identity provider's, which now waits for a click under break glass. No golden changed.
|
|
169
|
+
|
|
170
|
+
- Hardening of local sign-in (#555, ADR 0024, from #551): the password policy refuses an embedded
|
|
171
|
+
common-password list (SecLists, MIT, the entries of 12 to 128 characters, compared ignoring
|
|
172
|
+
case; rule `common_password`). Ten consecutive failed password checks, at sign-in or as a
|
|
173
|
+
password change's current password, lock an account for fifteen minutes, counted in a
|
|
174
|
+
transaction holding the account row so parallel attempts never pass ten; a success resets the
|
|
175
|
+
count. A locked account gets the wrong password's 401 at a hash's cost, its password unchecked
|
|
176
|
+
and its lock never extended, audited `locked_now` and then `locked`. A stored hash weaker than
|
|
177
|
+
the console's parameters is redone at the next successful sign-in. `meada ui reset-admin
|
|
178
|
+
--workspace <manifest>` (features `ui` and `accounts`) creates or reactivates `admin` as an
|
|
179
|
+
operator, clears its lock and sets the `MEADA_ADMIN_PASSWORD` value or a generated password
|
|
180
|
+
printed once on stdout, with a change required, recorded `account.reset_admin` `via` `cli`
|
|
181
|
+
before the write and refusing with exit 1 when the record cannot be written. No golden changed.
|
|
182
|
+
|
|
183
|
+
- Local sign-in for the console (#554, ADR 0024, from #551): the new `accounts` cargo feature
|
|
184
|
+
(enabled by `cloud`) and its `[accounts]` section, which needs `[postgres]` and never sits
|
|
185
|
+
beside `[oidc]`, name the Ed25519 signing key pair and the default account's initial password,
|
|
186
|
+
each from a variable or a file. Migration 9 adds the `accounts` table, so `meada postgres
|
|
187
|
+
migrate` reaches version 9. On its start the console checks the key pair and creates the
|
|
188
|
+
default account `admin` (password `admin123` with a change required, or the policy-checked
|
|
189
|
+
`MEADA_ADMIN_PASSWORD` without) once, under an advisory lock. `POST /api/v1/login` answers a
|
|
190
|
+
session token the console signs with EdDSA for eight hours; a token carrying the change-required
|
|
191
|
+
mark opens only `POST /api/v1/account/password`. Every route but the static files, `config` and
|
|
192
|
+
`login` then needs a session token; `[ui] operations = true` is accepted with `[accounts]` and
|
|
193
|
+
no `[oidc]`; `config` names the sign-in mode (`sign_in`: `accounts`, or `oidc` with an identity
|
|
194
|
+
provider), `session` adds `account: true`, and
|
|
195
|
+
every account reads every repository while no groups table bounds it. Passwords are argon2id at
|
|
196
|
+
OWASP's parameters under a policy of 12 to 128 characters that refuses the default password and
|
|
197
|
+
the username, at most four hashes run at once, and every sign-in, refusal and password change
|
|
198
|
+
is audited (`account.login`, `account.password`, role `none` for an unknown username) before its
|
|
199
|
+
token. The module table gains `accounts`; no golden changed.
|
|
200
|
+
|
|
201
|
+
- The console's sign-in pages for local accounts (#556, from #551): when `config` says
|
|
202
|
+
`"sign_in": "accounts"` the console shows its own sign-in page (labelled username and password,
|
|
203
|
+
one generic refusal, `busy` and `audit_unavailable` shown as themselves) instead of the identity
|
|
204
|
+
provider's redirect. A change-required sign-in goes straight to a forced password change page
|
|
205
|
+
(the current password and the new one twice, the server's rule shown on a refusal) that offers
|
|
206
|
+
nothing to navigate to until it succeeds, and then opens the workspace. The session token lives
|
|
207
|
+
in `sessionStorage` for the tab's life, is sent as the bearer and is cleared on sign-out and on
|
|
208
|
+
any 401 (which returns to sign-in; a refused current password in the change is not one); it is never in `localStorage`, a URL
|
|
209
|
+
or a log. A profile page offers the voluntary password change and sign-out. pt-BR and English
|
|
210
|
+
copy; the identity provider flow is unchanged. Front end only: no golden changed.
|
|
211
|
+
|
|
212
|
+
- `meada status` names a Kotlin file the grammar misreads (#546, from #434). A declaration read
|
|
213
|
+
as an infix call leaves the file out of the index; the file now sets the new `Facts::misparsed`
|
|
214
|
+
(absent from every other file's stored facts) instead of `unbuilt`, and a new status line,
|
|
215
|
+
`Msg::FileMisparsed`, in English and Portuguese, names it beside the byte-budget and using
|
|
216
|
+
drops. The Java and Kotlin layout skips it as it skips the other drops. The schema version is
|
|
217
|
+
the same: a file dropped before the upgrade gets its line when it next changes, or at once
|
|
218
|
+
after deleting `.meada/index.db`. The `cli.status-budget` goldens gained the new line.
|
|
219
|
+
|
|
220
|
+
### Changed
|
|
221
|
+
|
|
222
|
+
- The grant providers take neutral inputs (#553, from #551): the new `grant` module computes a
|
|
223
|
+
subject's grant from its groups and its GitHub login (`Providers::grant`), with no reference
|
|
224
|
+
to a token, and holds the GitHub grant provider's permissions cache, which moved out of the
|
|
225
|
+
OIDC module; the OIDC module feeds it from a token's claims. Every reader of `[oidc.github]`
|
|
226
|
+
goes through `Manifest::github`, the console and the proposal server build their sessions
|
|
227
|
+
from a neutral admitted subject (`grant::Admitted`), and a node's pass carries only a grant.
|
|
228
|
+
Nothing a caller sees changes; no golden changed.
|
|
229
|
+
|
|
230
|
+
- The axum provider reader walks each value once per file (#431): the values a file's rebound
|
|
231
|
+
`let`s reach share one `seen` set, and `Code::origins` is not asked for a call whose builder
|
|
232
|
+
chain goes through a method no router hands back, nor for a name written as text, a path, a
|
|
233
|
+
number, a boolean or a character. The reader's share of a one-file refresh on this repository
|
|
234
|
+
drops from about 1.4 s to about 0.1 s. No golden changed.
|
|
235
|
+
|
|
236
|
+
### Fixed
|
|
237
|
+
|
|
238
|
+
- Swift: a call whose labels differ from a known outside member's resolves as if that base
|
|
239
|
+
were absent (#463): `x.hash(seed: 1)` on a type that conforms to `Hashable` and declares
|
|
240
|
+
`hash(seed:)` is `exact`, while `x.hash(into: &h)` stays opaque. A call with no labels, or in
|
|
241
|
+
another language, is still compared by its bare name.
|
|
242
|
+
- Swift: an alias of an outside type reaches the repository's extensions of that type (#440). A
|
|
243
|
+
receiver typed by `typealias Anim = Animation`, or by an alias of an alias, and `Anim.build()`
|
|
244
|
+
match `extension Animation { }` as `Animation` does; an alias of an outside type with no
|
|
245
|
+
extension stays unresolved.
|
|
246
|
+
- Rust: a call after `?` or `.await` is typed by the value they unwrap (#435, after #401): the
|
|
247
|
+
pack keeps beside a function's written result the first type argument of a `Result` or
|
|
248
|
+
`Option` (`Def::unwrapped`) and the `Output = T` of `impl Future<Output = T>` and
|
|
249
|
+
`Pin<Box<dyn Future<Output = T>>>` (`Def::output`, read only through `.await`), so
|
|
250
|
+
`load()?.port()` and `fut().await.port()` resolve within `T`'s family, `exact` when it
|
|
251
|
+
declares one `port`, where `?` left a name match and a plain `fn` returning a future resolved
|
|
252
|
+
to nothing. A type outside the repository, or a `?` before an `.await`, leaves the call as
|
|
253
|
+
it was. The stored facts gain
|
|
254
|
+
`Def::unwrapped`, `Def::output`, `Call::unwraps` and `Call::awaits`, so the schema version
|
|
255
|
+
changes and Rust indexes are rebuilt once.
|
|
256
|
+
- Kotlin: a class, object or interface nested in an `expect` declaration, at any depth, is
|
|
257
|
+
`expect` too (#437), so a use of it resolves to the `expect` one instead of staying
|
|
258
|
+
`ambiguous` among its `actual` declarations.
|
|
259
|
+
- C# `using static T` imports only the static members and nested types `T` declares (#433): a bare
|
|
260
|
+
`Go()` with `Go` on a base of `T` was an `exact` link to the base's method, which C# rejects
|
|
261
|
+
("inherited members aren't imported"), and is now a name match at best; `using static` of the
|
|
262
|
+
base itself still gives it. Java's `import static` and Kotlin keep reading inherited members.
|
|
263
|
+
- Kotlin: a bare call resolves in Kotlin's order, an extension of the implicit receiver in scope
|
|
264
|
+
before a top-level function of its name (#436, from #402): inside `fun CoroutineScope.x() {
|
|
265
|
+
launch { } }` the call is `exact` to `CoroutineScope.launch`, not to the top-level `launch`
|
|
266
|
+
(`ambiguous` with it when the extension may apply to any receiver), and an `object`'s name is
|
|
267
|
+
its instance, so `Dispatchers.setMain(..)` reaches an imported `fun Dispatchers.setMain` (it
|
|
268
|
+
was no link) while a class's name keeps companion and statics. "Known ceilings" drops the
|
|
269
|
+
bare-call line. No golden changed.
|
|
270
|
+
- C#: an `internal`, `private` or `private protected` constructor or method of a public type is
|
|
271
|
+
a candidate from its own project's files alone (#441); `InternalsVisibleTo` stays unread.
|
|
272
|
+
- The console writes one `ui: directory: unreadable` stderr line per request when the directory
|
|
273
|
+
cannot be read (#451, after #335): the request's session remembers the failure at admission,
|
|
274
|
+
so the flags, the admission counts and the owner picker take that answer and write no second
|
|
275
|
+
line (`workspace` wrote two), and a write it refuses as 503 `audit_unavailable` prints no
|
|
276
|
+
pre-authentication audit line beside it. Reads still answer with the flags unavailable, the
|
|
277
|
+
counts null and the picker a 503; writes still refuse as before. No golden changed.
|
|
278
|
+
- Postgres calls that had no client-side deadline now have one (#447): a SCIM request (under the
|
|
279
|
+
directory's one write lock), the role check's fence read and write transaction, and the
|
|
280
|
+
console's start check, so a Postgres that accepts the connection and stops answering ends in a
|
|
281
|
+
503, an exit 1 with no exclusions file a reader admits, and a console that starts, instead of
|
|
282
|
+
holding them forever. `postgres::Config::bound(n)` now adds the version check's two statements
|
|
283
|
+
itself and every call site counts only its own (the audit and directory reads and the overage
|
|
284
|
+
lookup moved accordingly; the accounts' calls, which undercounted, and the permissions poll
|
|
285
|
+
gained the two). No golden changed.
|
|
286
|
+
- A crash after the pointer swap can no longer leave `current` naming a version document that
|
|
287
|
+
never reached the disk (#518): the pointer, the version document `meada workspace pull` writes,
|
|
288
|
+
the pulled contexts file and the exclusions file are replaced through one helper
|
|
289
|
+
(`pull::replace`) that syncs the new file before the rename and removes `<name>.new` when a
|
|
290
|
+
step fails. A failed pointer rename now names `current`, not `current.new`.
|
|
291
|
+
- The docs say what 1.0.0 ships: nine languages (TypeScript, JavaScript, Python, Go, Rust, Java,
|
|
292
|
+
Kotlin, C# and Swift). The three READMEs, the three 1.0.0 release notes and the three user
|
|
293
|
+
guides no longer call Java, Kotlin, C# and Swift later 1.x work, the user guides gain a section
|
|
294
|
+
for each of the four (9.5 to 9.8) with their brokers (JMS, Azure Service Bus) and package
|
|
295
|
+
ecosystems (Maven and Gradle, NuGet, SwiftPM), and ADR 0003 records the change in an
|
|
296
|
+
amendment. No code, default dependency or golden changed.
|
|
297
|
+
- A server-mode mirror's `meada.toml` and `meada.decisions.toml` are read through no symbolic
|
|
298
|
+
link (#547, after #506), as a pulled generation's are: `mirror()`, behind `Manifest::read`
|
|
299
|
+
(`mcp --listen`, snapshot pull, the lock and pointer operations, workspace versions, the
|
|
300
|
+
heartbeat, the UI, the workspaces CLI, the GitHub App), now refuses a link unopened, one that
|
|
301
|
+
stays inside the mirror included, a file that is not regular and a file replaced while read,
|
|
302
|
+
with the generation's messages, and bounds each file at 1 MiB (`GENERATION_CONFIG_MAX`, now
|
|
303
|
+
built without the `snapshot` feature). A local checkout and an operator's own files still
|
|
304
|
+
follow links. The architecture map and the snapshots page, in its three languages, say so.
|
|
305
|
+
- No manifest error quotes a written value (#545), after #449 stopped serde's `invalid type` and
|
|
306
|
+
`invalid value`: `unknown variant` names the key and the values it accepts (`` `workspace.source`:
|
|
307
|
+
is not one of the values it accepts (`file`, `store`) ``) instead of serde's text, an error no
|
|
308
|
+
key spans reads "a value is not valid here" instead of serde's message, and the rule errors
|
|
309
|
+
for `serve.prefix`, `serve.strip`, `serve.documents` and a resource's `kind` name the key and
|
|
310
|
+
the rule (`` `serve.strip`: must start with `/` ``) instead of the value. The console's cut of
|
|
311
|
+
an error to its position stays as a second guard (it still covers an error built outside
|
|
312
|
+
`describe` that names an identity). English and pt-BR texts changed; the workspace validation
|
|
313
|
+
fixture changed only by the new texts.
|
|
314
|
+
- The deploy fetch reads a `[[repository]]` entry by its own keys (#544): any table header ends
|
|
315
|
+
the entry before it, so a `[[repository.peer]]` or `[[repository.resource]]` table no longer
|
|
316
|
+
replaces its `repo` or `path`, and a value is the text between its quotes, so a trailing
|
|
317
|
+
comment is not part of it. Before, such a version stopped the Compose refresh and let the chart
|
|
318
|
+
clone the peer's repository into the entry's path (or into a directory named after the
|
|
319
|
+
comment). `fetch-pulled.sh` and the chart's `workspace.fetch` carry one awk program, and a
|
|
320
|
+
test fails when the two copies drift. No golden changed.
|
|
321
|
+
- A repository identity on the `[oidc.github]` host compares without case wherever it meets the
|
|
322
|
+
catalog (#508): the roles job gives a selected `github.com/Acme/API` and the catalog's
|
|
323
|
+
`github.com/acme/api` one `both` row keyed as written, the `max_repositories` cap does not
|
|
324
|
+
count it as extra, and the console's catalog check and listing match it. A repository selected
|
|
325
|
+
in two spellings (a deployment's `github.com/Acme/API`, a named workspace's
|
|
326
|
+
`github.com/acme/api`) keeps one `source` row under the first and gets its role rows under
|
|
327
|
+
each, so grants, which match exactly, read both. Other hosts compare exactly. No golden
|
|
328
|
+
changed.
|
|
329
|
+
- Compose mirror origins (#445): `fetch.sh` and `fetch-pulled.sh` read an existing mirror's
|
|
330
|
+
`origin` before fetching and refuse one whose HTTP(S) URL carries credentials (a mirror cloned
|
|
331
|
+
from a URL with a token keeps it there), naming the identity and never the URL, and the refresh
|
|
332
|
+
stops before index and publish as a failed fetch does. The READMEs tell the operator to run
|
|
333
|
+
`git remote set-url origin <URL without credentials>` in such a mirror.
|
|
334
|
+
- Java and Kotlin: a file with thousands of fields and locals is read in linear time (#442, from
|
|
335
|
+
#424). The hides check indexes the fields by name instead of scanning every field per local,
|
|
336
|
+
the class around a write is found from the prefixes of its scope, and `declared_before` (and
|
|
337
|
+
Kotlin's `assigned`) read a node's parent from an index built once per file, since
|
|
338
|
+
`Node::parent()` is found from the root and made a deep file quadratic per write. Same answers;
|
|
339
|
+
no golden changed.
|
|
340
|
+
- Indexing: a file a pack drops for passing a limit is named by `meada status` (#434, from
|
|
341
|
+
#419). The Java, Kotlin and Swift qualified-name budget (4 MiB) now sets `Facts::budget`, as the
|
|
342
|
+
C# one does, instead of `unbuilt`, which prints nothing; a C# project that gives its files more
|
|
343
|
+
than 256 usings (`PROJECT_USINGS`) marks each of them with the new `Facts::usings`, which a new
|
|
344
|
+
status line names (`Msg::FileTooManyUsings`, with the count). Kotlin's `misparsed` file stayed
|
|
345
|
+
`unbuilt` (a grammar defect, not a limit; #546 names it too). An index built before this change keeps a Java,
|
|
346
|
+
Kotlin or Swift file dropped by its budget as `unbuilt` until the file changes. No limit
|
|
347
|
+
changed. The `cli.status-budget` goldens gained the new cases; no stored format golden changed
|
|
348
|
+
(the new field is absent from every sample), so the schema version is the same.
|
|
349
|
+
- Resolution: the receiver and call depth (`RECEIVER_DEPTH`) is one count for the whole lookup
|
|
350
|
+
(#432, from #417), carried through a glob, an alias or an on-demand import as the link count is,
|
|
351
|
+
so a chain that alternates receivers and imports costs its length, not `RECEIVER_DEPTH` per link
|
|
352
|
+
up to `LINK_DEPTH`. No limit changed and no answer under the limits; no golden changed.
|
|
353
|
+
- Helm: the default `workspace.fetch` (#444, from #316) reads the repositories from `$1` when
|
|
354
|
+
given (the pulled list under `modules.oidc.github`) else from `workspace.repositories`, now
|
|
355
|
+
mounted as `repositories.toml` so a store-sourced refresh, whose bootstrap lists none, still
|
|
356
|
+
fetches the operator's list, refuses a URL carrying a credential and, as the compose
|
|
357
|
+
scripts do (#445), an existing mirror whose `origin` carries one, keeps each mirror strictly
|
|
358
|
+
under `/data/mirrors`, and on failure prints `refresh: fetch failed for <identity>; the refresh
|
|
359
|
+
stops before publication` and exits nonzero without echoing a URL or token.
|
|
360
|
+
`scripts/helm-check` runs the rendered script under `sh` with a stub `git` to check these; the
|
|
361
|
+
chart READMEs describe it.
|
|
362
|
+
- Workspace import (#450): `meada workspace import` reads its file once, bounded by the version
|
|
363
|
+
size limit, and audits the id of the text it stored; a file past the bound or not a regular
|
|
364
|
+
file is refused before any audit record is written.
|
|
365
|
+
- Manifest type errors (#449): a `meada.toml` or workspace manifest key of the wrong type, or
|
|
366
|
+
with an invalid value, reports the key and the expected kind (`` `oidc.entra`: has the wrong
|
|
367
|
+
type (a table was expected) ``) instead of serde's message, which echoed the written value, so a
|
|
368
|
+
secret pasted under the wrong key no longer reaches stderr.
|
|
369
|
+
- Pulled generations (#506): a mirror's `meada.toml` or `meada.decisions.toml` that is a symbolic
|
|
370
|
+
link is refused unopened, the error naming the file, so a repository can no longer make a node
|
|
371
|
+
read and parse a file of the host. A link into the mirror (`meada.toml -> conf/meada.toml`) is
|
|
372
|
+
refused too, as the index refuses a linked pack config. The file opened is checked to be the one
|
|
373
|
+
checked. Secrets and CAs a manifest names still follow links (Kubernetes mounts them through
|
|
374
|
+
one). The snapshots page says so in its three languages.
|
|
375
|
+
- Named workspaces on a node (#510): a node shows a named workspace's route
|
|
376
|
+
(`/-/workspaces/<id>/<identity>`, pinned or not) and lists it in a 404 only to a token whose
|
|
377
|
+
grant reads every entry of the workspace's version, the entries the sponsor rule excluded
|
|
378
|
+
included, as the console does. Before, once A of a Y+A workspace lost its sponsor, a subject
|
|
379
|
+
reading Y alone found the workspace on a node. A generation's context now records `excluded`,
|
|
380
|
+
the identities the sponsor rule left out, sorted, and its digest covers them; a context without
|
|
381
|
+
one is written as before, with the same generation id, and a generation published earlier reads
|
|
382
|
+
as none excluded. A node on an older binary refuses a generation that records an exclusion, so
|
|
383
|
+
upgrade nodes before or with the publisher. No golden changed.
|
|
384
|
+
|
|
385
|
+
## [1.0.0] - 2026-10-30
|
|
386
|
+
|
|
387
|
+
The tree declares `1.0.0`: this release raises the workspace, the `meada-core` pin, the Dockerfile,
|
|
388
|
+
the compose defaults and the Helm chart from `0.1.0`, and the `v1.0.0` tag follows its merge on
|
|
389
|
+
main. Publication is still ahead and belongs to the maintainer under
|
|
390
|
+
[#154](https://github.com/ClaudioMascaro/meada/issues/154): `cargo publish` of the crates (core
|
|
391
|
+
first), approval of the staged npm package with 2FA, and publication of the GitHub draft release,
|
|
392
|
+
which triggers the OCI image and Helm chart workflow.
|
|
393
|
+
Release notes and the scope evidence checklist are available in
|
|
394
|
+
[pt-BR](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.0.0.md),
|
|
395
|
+
[English](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.0.0.en.md) and
|
|
396
|
+
[Spanish](https://github.com/ClaudioMascaro/meada/blob/main/docs/releases/1.0.0.es.md).
|
|
397
|
+
The [1.x stability promise](https://github.com/ClaudioMascaro/meada/blob/main/docs/site/en/stability.md)
|
|
398
|
+
starts at publication. The [#32 tracking checklist](https://github.com/ClaudioMascaro/meada/issues/32)
|
|
399
|
+
still needs the post-publication evidence.
|
|
400
|
+
|
|
401
|
+
### Added
|
|
402
|
+
|
|
403
|
+
- Public fixture benchmark (issue #149): release-profile index/reindex timings, root and
|
|
404
|
+
workspace index sizes, and default-answer/tool-list token estimates in every PR/main CI
|
|
405
|
+
summary and retained JSON/Markdown artifact. Timings are informational.
|
|
406
|
+
|
|
407
|
+
- The English user guide and README (#150, spec #32): `docs/user-guide.en.md` translates both
|
|
408
|
+
halves of the pt-BR guide section by section (sections 1 to 11) with the same neutral examples
|
|
409
|
+
and links the English stability page; `README.en.md` now links it instead of the pt-BR guide.
|
|
410
|
+
No code, default dependency or golden changed.
|
|
411
|
+
- The Spanish user guide (#151, spec #32): `docs/user-guide.es.md`, sections 1 to 11 of the pt-BR
|
|
412
|
+
guide with the same structure and neutral names, linking the Spanish stability page. The Spanish
|
|
413
|
+
README links it instead of the Portuguese guide, and the three READMEs link the stability page
|
|
414
|
+
from the Status section. No code, default dependency or golden changed.
|
|
415
|
+
- The output grammar reference (#145, spec R1): `docs/reference/output-grammar.md`, in English like
|
|
416
|
+
the MCP surface, specifies every line kind of `search`, `context` and `trace`, the link notation
|
|
417
|
+
with its level and reason, the levels in order, the contract identifiers (`http::`, `http::ANY::`
|
|
418
|
+
for a provider of every method, `channel::`, `package::`, `resource::`), the `search` kinds, the
|
|
419
|
+
chain footer, the cut note and the token estimate, and tells readers to skip line kinds and
|
|
420
|
+
fields they do not know. Its tables are the grammar check's input: `tests/it/grammar.rs` matches
|
|
421
|
+
every line of every rendered-answer golden against the line kinds of its tool and fails naming
|
|
422
|
+
the golden and the line, fails on a documented line kind no golden shows, and holds the
|
|
423
|
+
document's levels, entry kinds, open item kinds and `search` kinds to the code's. The stability
|
|
424
|
+
document links it. No output changed; new goldens pin the answers only inline assertions covered (`no symbol
|
|
425
|
+
matches`, `no resource matches`, the server's `index behind the mirror`, and `trace` with no
|
|
426
|
+
start, several symbols, several call sites or a clean working tree).
|
|
427
|
+
- The pt-BR user guide, second half (#147, spec #32), in `docs/user-guide.md` (sections 8 to 11):
|
|
428
|
+
each contract kind (HTTP routes, declared resources and gateway prefixes, OpenAPI and AsyncAPI
|
|
429
|
+
documents, channels with the limit that broker clusters are not modelled, packages), each 1.0
|
|
430
|
+
language pack (TypeScript and JavaScript, Python, Go, Rust) with its frameworks, clients,
|
|
431
|
+
environment reads, manifests, channel clients and known limits (including that Rust calls inside
|
|
432
|
+
macros are not indexed), shape drift, and communities and processes. Java, Kotlin, C# and Swift
|
|
433
|
+
are named only as planned Release 2 work. No code, default dependency or golden changed.
|
|
434
|
+
- The pt-BR user guide, first half (#146, spec #32), in `docs/user-guide.md`: installation through
|
|
435
|
+
every channel (Cargo, prebuilt binary, shell installer, `npx @meada/meada`, container), MCP setup with
|
|
436
|
+
`npx @meada/meada mcp` and the three tools with their parameters, the `meada.toml` reference (every
|
|
437
|
+
table and key), decisions and deciders (protocols, environment variables, what is sent,
|
|
438
|
+
privacy), every CLI command and the export. The READMEs in all three languages gain the
|
|
439
|
+
installation channels, first steps, MCP setup and a 1.0 status section with the stability
|
|
440
|
+
promise. No code, default dependency or golden changed.
|
|
441
|
+
- Surface goldens (#144, spec #32): `tests/golden/mcp.tools.json` holds the MCP tool list (names,
|
|
442
|
+
descriptions and parameter schemas of `search`, `context` and `trace`), checked beside the
|
|
443
|
+
1,000-token limit of the descriptions, and `tests/golden/cli.help-all.en.txt` the English help of
|
|
444
|
+
every command of the default build. A test pins the default token budget of 2,000. Both
|
|
445
|
+
goldens change only with `MEADA_BLESS=1`.
|
|
446
|
+
- The stability document (#148, spec #32), `docs/site/{pt,en,es}/stability.md`: the surface 1.x
|
|
447
|
+
freezes (the MCP tools, the output grammar, CLI commands and flags, the `meada.toml`,
|
|
448
|
+
`meada.decisions.toml` and `meada.workspace.toml` schemas, the export), what is breaking, what is
|
|
449
|
+
minor, what is not frozen, and the review gate. The READMEs and the site home pages link it.
|
|
450
|
+
- `search`, `context` and `trace` read from each index its contract rows and only the symbols,
|
|
451
|
+
calls and communities of their answer (#396, **Partial export**), instead of every row of every
|
|
452
|
+
repository. Answers are the same bytes; on junit5 a `search` or `context` peaks at about 40 MB
|
|
453
|
+
instead of 170 to 190 MB and answers in about 0.3 s instead of 1 to 1.4 s. The index gains
|
|
454
|
+
seven lookup indexes (about 40% larger on junit5) and its schema version changes, so existing
|
|
455
|
+
indexes are rebuilt. `meada export`, `status` and the decision report still read every row.
|
|
456
|
+
- A Meada skill for agents, `skills/meada/SKILL.md`: when to reach for `search`, `context` and
|
|
457
|
+
`trace`, how to read each level, and that a missing caller is unproven. The READMEs and the
|
|
458
|
+
site's MCP page show how to install it.
|
|
459
|
+
- Per-channel install and MCP setup: the READMEs open with one row per channel (npx, Cargo, shell
|
|
460
|
+
installer, archive, Docker) with its install line and MCP server command, and gain a Docker MCP
|
|
461
|
+
line that mounts the folder holding the repository at the same path and runs without a network.
|
|
462
|
+
`scripts/container-smoke` runs that line as a stdio client.
|
|
463
|
+
- The site's Deploy page (`docs/site/{pt,en,es}/deploy.md`) covers Docker, Compose and Helm, and
|
|
464
|
+
the chart gains `values-minimal.yaml`, which `scripts/helm-check` renders.
|
|
465
|
+
|
|
466
|
+
### Changed
|
|
467
|
+
|
|
468
|
+
- For `meada-core` crate users: the export's structs (`Export` and each of its pieces, with
|
|
469
|
+
`Shape` and `Drift`) are `#[non_exhaustive]`, so a field added in 1.x is a minor change. Build
|
|
470
|
+
one with `T::default()` and named field assignments, or, for a struct with a field that has no
|
|
471
|
+
default (`Document`, `Import`, `Link`, `Process`, `Step`, `Stale`), with `T::new` taking every
|
|
472
|
+
field in declaration order (`Shape::new` takes the source, the rest set after it). A struct
|
|
473
|
+
literal or an exhaustive pattern of these types outside `meada-core` no longer compiles. No
|
|
474
|
+
output, golden or exported byte changed.
|
|
475
|
+
- The stability promise (spec #32) lets 1.x grow the MCP surface. In
|
|
476
|
+
`docs/site/{pt,en,es}/stability.md` and the three READMEs, these are minor changes: adding an MCP
|
|
477
|
+
tool while the tool list stays within its 1,000-token budget, adding an accepted value to an
|
|
478
|
+
existing parameter (a new value of `changes`) and adding a field at the end of an existing line
|
|
479
|
+
kind. Removing or renaming a tool or parameter and changing what an existing one means stay
|
|
480
|
+
breaking. ADR 0008 is amended: three tools is where the surface started, not a ceiling.
|
|
481
|
+
- `SECURITY` (pt-BR, English and Spanish): the latest published 1.x version receives security
|
|
482
|
+
fixes, which ship as a patch or minor release.
|
|
483
|
+
|
|
484
|
+
### Fixed
|
|
485
|
+
|
|
486
|
+
- Console GitHub grant (#496): a session's GitHub grant and its state (`unread`, `current`,
|
|
487
|
+
`expired`) are read from the same permissions set at the same instant, so a session never shows
|
|
488
|
+
`expired` with a grant read while the set was fresh.
|
|
489
|
+
- Release preparation keeps the GitHub release in draft state for the maintainer to publish.
|
|
490
|
+
A pinned cargo-dist regeneration helper compares the entire workflow after the explicit
|
|
491
|
+
draft policy; OCI publication follows the human `release: published` event.
|
|
492
|
+
|
|
493
|
+
### Prepared
|
|
494
|
+
|
|
495
|
+
- The v1 scope: HTTP, declared resources and gateway paths, OpenAPI/AsyncAPI, channels and
|
|
496
|
+
packages; levels and cross-repository chains, recorded decisions with optional deciders,
|
|
497
|
+
shape drift, TypeScript/JavaScript, Python, Go, Rust, communities and processes.
|
|
498
|
+
- The R1 stability promise, normative MCP output grammar, surface goldens, complete user
|
|
499
|
+
references and public-fixture CI benchmark. Fixture timings are informational.
|
|
500
|
+
- Configured Cargo, binary, shell, npm and OCI distribution. Configuration is not evidence
|
|
501
|
+
of actual publication or a successful published-installer smoke check.
|
|
502
|
+
|
|
503
|
+
### Acceptance
|
|
504
|
+
|
|
505
|
+
The [public #152 receipt](https://github.com/ClaudioMascaro/meada/issues/152#issuecomment-6379316350)
|
|
506
|
+
retains both complete runs on AMD Ryzen 7 5825U, 16 logical CPUs, 7.16 GiB RAM,
|
|
507
|
+
Ubuntu 24.04.5 LTS, x86_64. The measured build was
|
|
508
|
+
`9b99c3a4091b6c1b2c590c43059763f25b6987ef`, `meada 0.1.0`, not every later documentation head.
|
|
509
|
+
|
|
510
|
+
| Metric | Target | First complete run | Complete rerun |
|
|
511
|
+
| --- | --- | --- | --- |
|
|
512
|
+
| Cold configured-workspace index | <= 7 s | 12.680 s, not met | 2.711 s, met |
|
|
513
|
+
| Root index size | <= 37 MB | 21.057536 MB, met | 21.057536 MB, met |
|
|
514
|
+
| Single-file configured-workspace reindex | <= 1 s | 1.346 s, not met | 1.152 s, not met |
|
|
515
|
+
| Compact MCP `tools/list` result | <= 1,000 tokens | 622, met | 622, met |
|
|
516
|
+
| Largest default answer among 11 queries | <= 2,000 tokens | 1,996, met | 1,996, met |
|
|
517
|
+
|
|
518
|
+
MB means 10^6 bytes; tokens are ceil(UTF-8 bytes / 4). Public fixture peers supplement the
|
|
519
|
+
private workload; the receipt does not claim every feature naturally occurs in the private root.
|
|
520
|
+
The [rerun of 2026-10-30](https://github.com/ClaudioMascaro/meada/issues/152#issuecomment-6531862493)
|
|
521
|
+
on main `1d648ad6` uses a reconstructed workspace (not directly comparable) and meets four of the
|
|
522
|
+
five targets: cold index (medians 5.586 to 6.625 s, <= 7 s), root index size (31.883266 MB,
|
|
523
|
+
<= 37 MB), `tools/list` (643 tokens, <= 1,000) and largest default answer (1,999 tokens,
|
|
524
|
+
<= 2,000). The single-file reindex (<= 1 s) met the target in the two quieter runs (0.99 and
|
|
525
|
+
0.931 s) and missed it in the two runs at a load average near 3 (1.068 and 1.123 s). The
|
|
526
|
+
maintainer [waived the reindex target for 1.0.0](https://github.com/ClaudioMascaro/meada/issues/350#issuecomment-6532716065),
|
|
527
|
+
recorded on [#350](https://github.com/ClaudioMascaro/meada/issues/350).
|
|
528
|
+
|
|
529
|
+
Known limit: the single-file reindex sits near 1 s and exceeds it under load. #350 stays open for
|
|
530
|
+
1.x, with the goal of 1 s with headroom under ordinary load; a speedup changes no output, so it
|
|
531
|
+
ships as a patch or minor release. Publication is done separately by the maintainer under
|
|
532
|
+
[#154](https://github.com/ClaudioMascaro/meada/issues/154).
|
|
533
|
+
|
|
9
534
|
## [0.1.0] - 2026-10-30
|
|
10
535
|
|
|
11
536
|
The first release: the trunk of the roadmap (ADR 0003) and every spec merged since, with
|
|
@@ -555,5 +1080,7 @@ and `trace` from the two longest processes. The spec adds about 0.3 MB and 0.03
|
|
|
555
1080
|
The rise of the single-file reindex since 2026-10-14 predates it (specs #22 and #23), and at
|
|
556
1081
|
692 files it is close to its target.
|
|
557
1082
|
|
|
558
|
-
[Unreleased]: https://github.com/ClaudioMascaro/meada/compare/
|
|
1083
|
+
[Unreleased]: https://github.com/ClaudioMascaro/meada/compare/v1.1.0...HEAD
|
|
1084
|
+
[1.1.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.1.0
|
|
1085
|
+
[1.0.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v1.0.0
|
|
559
1086
|
[0.1.0]: https://github.com/ClaudioMascaro/meada/releases/tag/v0.1.0
|
package/README.md
CHANGED
|
@@ -9,13 +9,127 @@ LLM.
|
|
|
9
9
|
|
|
10
10
|
## Instalação
|
|
11
11
|
|
|
12
|
+
Escolha a linha que combina com o que você já tem. Todos os canais entregam o mesmo binário
|
|
13
|
+
`meada`, e a última coluna é o comando que a configuração MCP do seu agente executa.
|
|
14
|
+
|
|
15
|
+
| Você tem | Instalação | Comando do servidor MCP |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Node.js | nada: `npx -y @meada/meada --version` | `npx -y @meada/meada mcp` |
|
|
18
|
+
| Rust | `cargo install meada` | `meada mcp` |
|
|
19
|
+
| Linux ou macOS | o instalador de shell abaixo | `meada mcp` |
|
|
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) |
|
|
22
|
+
|
|
23
|
+
```sh
|
|
24
|
+
# Instalador de shell (Linux e macOS)
|
|
25
|
+
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/ClaudioMascaro/meada/releases/latest/download/meada-installer.sh | sh
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Os arquivos prontos cobrem Linux, macOS e Windows, em x86_64 e arm64; a imagem cobre Linux amd64
|
|
29
|
+
e arm64. A versão do pacote npm é sempre a da release. Para indexar, o Meada só precisa do
|
|
30
|
+
binário e do git. Os detalhes de cada canal, da console e do contêiner estão em
|
|
31
|
+
[Instalação](https://claudiomascaro.github.io/meada/installation/) e no
|
|
32
|
+
[guia do usuário](docs/user-guide.md) (seção 1, Instalação).
|
|
33
|
+
|
|
34
|
+
## Primeiros passos
|
|
35
|
+
|
|
36
|
+
Na raiz de um repositório (aqui `web`, que consome a rota de `api`):
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
meada index # monta o índice em .meada/, do repositório e dos pares
|
|
40
|
+
meada status # o estado de cada índice e os pares não encontrados
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Para o Meada ligar `web` a `api`, o `meada.toml` de `web` nomeia o par:
|
|
44
|
+
|
|
45
|
+
```toml
|
|
46
|
+
[[peer]]
|
|
47
|
+
repo = "example.com/acme/api" # remoto git de origin, sem esquema nem .git
|
|
48
|
+
base_url_env = ["API_URL"] # variável de onde o cliente lê a URL base
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A referência completa do `meada.toml` está no
|
|
52
|
+
[guia do usuário](docs/user-guide.md) (seção 4, referência do `meada.toml`).
|
|
53
|
+
|
|
54
|
+
## Conectar um agente (MCP)
|
|
55
|
+
|
|
56
|
+
O cliente executa o comando do servidor MCP e fala com o Meada por stdio. Na configuração do seu
|
|
57
|
+
agente (por exemplo o `.mcp.json` do Claude Code), com npx:
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"meada": { "command": "npx", "args": ["-y", "@meada/meada", "mcp"] }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
No Claude Code, o mesmo em uma linha: `claude mcp add meada -- npx -y @meada/meada mcp`. Com
|
|
68
|
+
`meada` já no `PATH` (Cargo, instalador ou arquivo pronto), use
|
|
69
|
+
`"command": "meada", "args": ["mcp"]`.
|
|
70
|
+
|
|
71
|
+
Com Docker (Linux e macOS):
|
|
72
|
+
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"mcpServers": {
|
|
76
|
+
"meada": {
|
|
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"]
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
O cliente inicia o servidor no seu repositório. O Meada responde sobre o caminho que o cliente
|
|
85
|
+
envia como raiz, então o contêiner monta a pasta que contém o repositório, e os pares vizinhos,
|
|
86
|
+
nesse mesmo caminho; roda com o seu usuário, para o `.meada/` continuar seu, e sem rede, que nem
|
|
87
|
+
a indexação nem o stdio usam.
|
|
88
|
+
|
|
89
|
+
O agente ganha três ferramentas, `search`, `context` e `trace`, que só leem. Veja
|
|
90
|
+
[Agentes e MCP](https://claudiomascaro.github.io/meada/mcp/) e o
|
|
91
|
+
[guia do usuário](docs/user-guide.md) (seção 2, Conectar um agente).
|
|
92
|
+
|
|
93
|
+
### Skill para agentes
|
|
94
|
+
|
|
95
|
+
[`skills/meada/SKILL.md`](skills/meada/SKILL.md) ensina o agente a escolher cada ferramenta e a
|
|
96
|
+
ler os níveis de uma resposta. No Claude Code:
|
|
97
|
+
|
|
12
98
|
```sh
|
|
13
|
-
|
|
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
|
|
14
101
|
```
|
|
15
102
|
|
|
16
|
-
|
|
103
|
+
Outros agentes: veja [Agentes e MCP](https://claudiomascaro.github.io/meada/mcp/#skill-para-agentes).
|
|
104
|
+
|
|
105
|
+
## Status
|
|
106
|
+
|
|
107
|
+
Meada 1.0 entrega todo o escopo da v1 do [ADR 0003](docs/adr/0003-v1-scope-and-roadmap.md):
|
|
108
|
+
|
|
109
|
+
- **Contratos**: rotas HTTP, recursos declarados, documentos OpenAPI e AsyncAPI, filas e
|
|
110
|
+
tópicos, pacotes.
|
|
111
|
+
- **Níveis**: um nível em cada ligação, cadeias que atravessam repositórios e decisões com
|
|
112
|
+
decisor opcional (`meada decide`).
|
|
113
|
+
- **Análises**: drift de forma, comunidades e processos.
|
|
114
|
+
- **Linguagens no 1.0**: nove, TypeScript, JavaScript, Python, Go, Rust, Java, Kotlin, C# e
|
|
115
|
+
Swift (#26 a #29, ADR 0003).
|
|
116
|
+
|
|
117
|
+
**Promessa de estabilidade.** A partir do 1.0 vale o semver: uma mudança incompatível em um
|
|
118
|
+
destes itens pede uma versão major.
|
|
119
|
+
|
|
120
|
+
- os nomes, os parâmetros e a gramática de saída das ferramentas MCP (`search`, `context` e
|
|
121
|
+
`trace` hoje);
|
|
122
|
+
- os comandos e as flags da CLI;
|
|
123
|
+
- os esquemas do `meada.toml` e do `meada.decisions.toml`;
|
|
124
|
+
- o formato do `meada export`.
|
|
17
125
|
|
|
18
|
-
|
|
126
|
+
Acrescentar uma ferramenta MCP, um parâmetro opcional, um valor aceito a um parâmetro, um tipo de
|
|
127
|
+
busca, um campo no fim de uma linha da saída, uma chave de configuração, um campo do export ou
|
|
128
|
+
uma linguagem é mudança menor. Não entram na promessa o texto das mensagens da CLI, o
|
|
129
|
+
texto das descrições das ferramentas, o arquivo de índice e o layout de `.meada/` (reconstruídos
|
|
130
|
+
quando o esquema muda) e quais ligações o Meada encontra num código (melhorar a resolução é
|
|
131
|
+
correção, não quebra). O detalhe do que é congelado e do que não é está em
|
|
132
|
+
[Estabilidade](https://claudiomascaro.github.io/meada/stability/).
|
|
19
133
|
|
|
20
134
|
## Alimentar uma base de conhecimento
|
|
21
135
|
|
|
@@ -65,11 +179,14 @@ Meada (invariante 1, [ADR 0002](docs/adr/0002-product-invariants.md)).
|
|
|
65
179
|
|
|
66
180
|
## Documentação
|
|
67
181
|
|
|
182
|
+
- [Guia do usuário](docs/user-guide.md)
|
|
68
183
|
- [Configuração](https://claudiomascaro.github.io/meada/configuration/)
|
|
69
184
|
- [Agentes e MCP](https://claudiomascaro.github.io/meada/mcp/)
|
|
70
185
|
- [Modo servidor](https://claudiomascaro.github.io/meada/server/)
|
|
186
|
+
- [Implantar com Docker, Compose ou Helm](https://claudiomascaro.github.io/meada/deploy/)
|
|
71
187
|
- [Console](https://claudiomascaro.github.io/meada/console/)
|
|
72
188
|
- [Capacidades e limites](https://claudiomascaro.github.io/meada/capabilities/)
|
|
189
|
+
- [Estabilidade](https://claudiomascaro.github.io/meada/stability/)
|
|
73
190
|
- [Participar](https://claudiomascaro.github.io/meada/contributing/)
|
|
74
191
|
|
|
75
192
|
[Apache-2.0](LICENSE).
|
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": "
|
|
22
|
+
"version": "1.1.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": "
|
|
51
|
+
"version": "1.1.0"
|
|
52
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"artifactDownloadUrls": [
|
|
3
|
-
"https://github.com/ClaudioMascaro/meada/releases/download/
|
|
3
|
+
"https://github.com/ClaudioMascaro/meada/releases/download/v1.1.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": "
|
|
92
|
+
"version": "1.1.0",
|
|
93
93
|
"volta": {
|
|
94
94
|
"node": "18.14.1",
|
|
95
95
|
"npm": "9.5.0"
|