feat(package): read manifest sources and registry URLs as Uri, and lock the canonical text #216

Merged
argus merged 2 commits from loop/26-uri-manifest into main 2026-10-08 18:42:17 +00:00
Collaborator

Closes #26

URI slice 9 (docs/design/URI.md), option A as decided on the issue.

What changed

  • Registry URLs. registry "...", url: with https: or http: is read as a Uri (registryUrlOf in compiler/src/project/manifest.trb) and kept as the canonical text of uri.normalized(): lower-case scheme and host, no default port, / for an empty path. publicRegistry is now https://packages.torb.dev/.
  • file: registries keep the relative directory as written, because Uri resolves file:../registry to file:registry.
  • Sources. git: and archive: locations are parsed into SourceBinding.uri, a Uri? that is None for path:. path: stays a directory.
  • Errors at the manifest line. locationProblemsOf adds a ManifestProblem at the string literal for a registry URL that is no URI or is neither https: nor http:, and for a git:/archive: location that is no URI. It runs as part of manifestProblemsOf, so torb check reports --> project.trb:line:col. The package commands (contextOf in compiler/src/cli/packages.trb) refuse the first one before anything is fetched or written.
  • Lock. readLock reads registry: through registryUrlOf, so a lock from before this change (https://packages.torb.dev) is the same registry. It gives no mismatch against the binding, and torb lock writes it once in the canonical form. torb lock --check fails on an old lock until that rewrite is done. No lock in this repository has an https: registry, so nothing here needs rewriting.

Decisions

  • std/project stays on String. The receiver types of Registry/Source stay String. A file: registry is no Uri, and the checked-literal rule would refuse it. The toolchain's static reader does the URI reading, which is where the errors with a place come from anyway.
  • Cache paths are unchanged. RegistryLocation.Web still drops the trailing /, so cache keys and paths stay the same. The shipped-key comparison in webRegistryKeys ignores a trailing / on both sides.
  • The lock keeps the full text. It records Uri.text(), not the password-redacting show(), which matches the previous as-written behaviour. Messages use show().
  • No resolver for git:/archive: yet. They are still not resolved or locked. The parsed uri is there for the resolver when it lands.
  • Seed: no impact. There is no syntax, native or driver change. The compiler already depends on std/uri. So no two-commit split is needed.

Tests

  • compiler/tests/project.test.trb
    • The canonical registry URL.
    • file: kept as written.
    • The source URIs, with path: as None.
    • The problems: a bad host, ftp:, a scp-style git@host:x.git, a relative archive.
    • The span of the problem is the string literal.
    • The workspace problem at project.trb:3:23.
  • compiler/tests/packages.test.trb
    • An old lock reads as publicRegistry, renders as https://packages.torb.dev/, and rendering again is stable. file: is untouched.
    • The binding-mismatch message now names the canonical URL.

Docs

  • URI.md: slice 9 is marked done, with the status line and the section 10 table updated.
  • PROJECT.md sections 7 and 11.
  • docs/tooling/project-trb.md and project-lock-trb.md.
  • skills/ regenerated.

Follow-ups

  • Resolving and locking git: and archive: sources, using SourceBinding.uri.
  • None for the seed.
Closes #26 URI slice 9 (docs/design/URI.md), option A as decided on the issue. ## What changed - **Registry URLs.** `registry "...", url:` with `https:` or `http:` is read as a `Uri` (`registryUrlOf` in `compiler/src/project/manifest.trb`) and kept as the canonical text of `uri.normalized()`: lower-case scheme and host, no default port, `/` for an empty path. `publicRegistry` is now `https://packages.torb.dev/`. - **`file:` registries** keep the relative directory as written, because `Uri` resolves `file:../registry` to `file:registry`. - **Sources.** `git:` and `archive:` locations are parsed into `SourceBinding.uri`, a `Uri?` that is `None` for `path:`. `path:` stays a directory. - **Errors at the manifest line.** `locationProblemsOf` adds a `ManifestProblem` at the string literal for a registry URL that is no URI or is neither `https:` nor `http:`, and for a `git:`/`archive:` location that is no URI. It runs as part of `manifestProblemsOf`, so `torb check` reports `--> project.trb:line:col`. The package commands (`contextOf` in `compiler/src/cli/packages.trb`) refuse the first one before anything is fetched or written. - **Lock.** `readLock` reads `registry:` through `registryUrlOf`, so a lock from before this change (`https://packages.torb.dev`) is the same registry. It gives no mismatch against the binding, and `torb lock` writes it once in the canonical form. `torb lock --check` fails on an old lock until that rewrite is done. No lock in this repository has an `https:` registry, so nothing here needs rewriting. ## Decisions - **std/project stays on `String`.** The receiver types of `Registry`/`Source` stay `String`. A `file:` registry is no `Uri`, and the checked-literal rule would refuse it. The toolchain's static reader does the URI reading, which is where the errors with a place come from anyway. - **Cache paths are unchanged.** `RegistryLocation.Web` still drops the trailing `/`, so cache keys and paths stay the same. The shipped-key comparison in `webRegistryKeys` ignores a trailing `/` on both sides. - **The lock keeps the full text.** It records `Uri.text()`, not the password-redacting `show()`, which matches the previous as-written behaviour. Messages use `show()`. - **No resolver for `git:`/`archive:` yet.** They are still not resolved or locked. The parsed `uri` is there for the resolver when it lands. - **Seed: no impact.** There is no syntax, native or driver change. The compiler already depends on `std/uri`. So no two-commit split is needed. ## Tests - `compiler/tests/project.test.trb` - The canonical registry URL. - `file:` kept as written. - The source URIs, with `path:` as `None`. - The problems: a bad host, `ftp:`, a scp-style `git@host:x.git`, a relative archive. - The span of the problem is the string literal. - The workspace problem at `project.trb:3:23`. - `compiler/tests/packages.test.trb` - An old lock reads as `publicRegistry`, renders as `https://packages.torb.dev/`, and rendering again is stable. `file:` is untouched. - The binding-mismatch message now names the canonical URL. ## Docs - URI.md: slice 9 is marked done, with the status line and the section 10 table updated. - PROJECT.md sections 7 and 11. - docs/tooling/project-trb.md and project-lock-trb.md. - skills/ regenerated. ## Follow-ups - Resolving and locking `git:` and `archive:` sources, using `SourceBinding.uri`. - None for the seed.
docs(uri): slice 9 done, the manifest's locations are Uris and the lock records the canonical text
All checks were successful
pdisc / pdisc (pull_request) Successful in 11s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 50s
ci / tier A (linux-x64) (pull_request) Successful in 2m56s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m47s
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 16s
ci / bootstrap (linux-x64) (pull_request) Successful in 2m58s
ci / tier B (linux-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / commit messages (pull_request) Successful in 5s
ci / what the change touches (pull_request) Successful in 5s
ci / every host emits the same C (pull_request) Successful in 4m34s
ci / pack the seed (pull_request) Successful in 12s
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
3bc8c81f0e
argus approved these changes 2026-10-08 18:42:16 +00:00
argus left a comment

Checklist at 3bc8c81 (CI combined status success: tier A, bootstrap, playground, pdisc, every-host-same-C).

  • Tests: ok. New cases cover the canonical registry URL, file: as written, source URIs with path: as None, the problems (bad host, ftp:, scp-style git@host:x.git, relative archive), the string-literal span, the workspace problem at project.trb:3:23, and the old-lock read/rewrite/stable-rerender round trip.
  • Correctness: ok. registryUrlOf is the single reader used by the manifest, the lock and the problem check. RegistryLocation.Web still drops the trailing /, so cache keys and paths stay the same, and the webRegistryKeys comparison now ignores a trailing / on both sides, so the shipped key still matches publicRegistry. A pre-change lock reads as the same registry, so there is no binding mismatch. No lock in the repo has an https: registry.
  • Scope: ok. Issue #26 acceptance criteria are all met: URIs with errors at the manifest line, the lock records the canonical text, URI.md slice 9 marked done. std/project receiver types are deliberately unchanged.
  • Security/data: ok. Nothing is fetched before a bad location is refused. The lock keeps text(), as before, and messages use show(). The lock format changes only by the trailing /, with a documented one-time rewrite (torb lock --check fails on an old lock until then).
  • Docs: ok. URI.md, PROJECT.md 7 and 11, the tooling pages and the regenerated skills/ copies are updated.
  • Architecture/placement: no new boundary.

Non-blocking:

  1. locationProblemLines and the early refusal in contextOf (compiler/src/cli/packages.trb) have no direct test; the covered path is manifestProblemsOf via findWorkspace. A CLI-level case ("torb lock refuses a bad registry URL before any fetch") would pin the claim in the PR body.
  2. webRegistryKeys trailing-slash handling has no dedicated test; the shipped-key lookup for publicRegistry is the case worth asserting.
Checklist at 3bc8c81 (CI combined status success: tier A, bootstrap, playground, pdisc, every-host-same-C). - **Tests:** ok. New cases cover the canonical registry URL, `file:` as written, source URIs with `path:` as `None`, the problems (bad host, `ftp:`, scp-style `git@host:x.git`, relative archive), the string-literal span, the workspace problem at `project.trb:3:23`, and the old-lock read/rewrite/stable-rerender round trip. - **Correctness:** ok. `registryUrlOf` is the single reader used by the manifest, the lock and the problem check. `RegistryLocation.Web` still drops the trailing `/`, so cache keys and paths stay the same, and the `webRegistryKeys` comparison now ignores a trailing `/` on both sides, so the shipped key still matches `publicRegistry`. A pre-change lock reads as the same registry, so there is no binding mismatch. No lock in the repo has an `https:` registry. - **Scope:** ok. Issue #26 acceptance criteria are all met: URIs with errors at the manifest line, the lock records the canonical text, URI.md slice 9 marked done. `std/project` receiver types are deliberately unchanged. - **Security/data:** ok. Nothing is fetched before a bad location is refused. The lock keeps `text()`, as before, and messages use `show()`. The lock format changes only by the trailing `/`, with a documented one-time rewrite (`torb lock --check` fails on an old lock until then). - **Docs:** ok. URI.md, PROJECT.md 7 and 11, the tooling pages and the regenerated skills/ copies are updated. - **Architecture/placement:** no new boundary. Non-blocking: 1. `locationProblemLines` and the early refusal in `contextOf` (`compiler/src/cli/packages.trb`) have no direct test; the covered path is `manifestProblemsOf` via `findWorkspace`. A CLI-level case ("torb lock refuses a bad registry URL before any fetch") would pin the claim in the PR body. 2. `webRegistryKeys` trailing-slash handling has no dedicated test; the shipped-key lookup for `publicRegistry` is the case worth asserting.
argus merged commit 95ac04333d into main 2026-10-08 18:42:17 +00:00
argus deleted branch loop/26-uri-manifest 2026-10-08 18:42:18 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!216
No description provided.