Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1744fd3
feat: run BReg and Casework together for development
jeremi Nov 10, 2026
149965e
fix: handle completed tool groups on macOS
jeremi Nov 10, 2026
f73f53b
fix: align project development with product contracts
jeremi Nov 10, 2026
e67d61c
test: avoid storing development test passwords
jeremi Nov 10, 2026
14d8d9d
fix: complete development run database setup
jeremi Nov 10, 2026
c9068be
fix: explain plan refusals and bound database operations
jeremi Nov 10, 2026
2fa5d2a
fix: resolve development plan references before allocation
jeremi Nov 10, 2026
6b531c0
fix: validate product references offline and enforce poll deadlines
jeremi Nov 10, 2026
6dd2fa4
feat(casework): list access profiles in caseworkctl explain
jeremi Nov 10, 2026
b9f416a
fix(bregctl): log dev product output, record process groups, check gr…
jeremi Nov 10, 2026
0b327f8
refactor(bregctl): name every database object a dev run can own
jeremi Nov 10, 2026
4b776d6
fix(bregctl): explain failed dev journey steps and report interruptio…
jeremi Nov 10, 2026
449c43f
fix(bregctl): keep failed dev run logs, bound cleanup and report a lo…
jeremi Nov 10, 2026
5ef5c14
fix(bregctl): let a least-privilege admin run dev databases and name …
jeremi Nov 10, 2026
4bac0ae
docs(bregctl): describe every dev plan field in the generated schema
jeremi Nov 10, 2026
03264b8
fix: honour dev --json for launcher failures and require only the pla…
jeremi Nov 10, 2026
06d3a2f
refactor: read the dev plan's products with the YAML reader
jeremi Nov 10, 2026
9f840fb
test(rstack): prove least-privilege admin, kept logs and lost-supervi…
jeremi Nov 10, 2026
85272d7
fix(bregctl): accept dev grants that name proposal-only BReg profiles
jeremi Nov 10, 2026
36de460
fix(bregctl): remove a dev run directory in one step so status never …
jeremi Nov 10, 2026
ecda759
test(rstack): ignore dev runs being deleted and check none are left b…
jeremi Nov 10, 2026
5200fb9
docs(platform): document dev run admin rules, recovery and logs
jeremi Nov 10, 2026
5ff937a
docs(platform): group dev run failure handling under its own heading
jeremi Nov 10, 2026
585b1fd
docs(platform): name proposal-only BReg profiles and interrupted run …
jeremi Nov 10, 2026
76a8c4e
test(bregctl): give the binding-ID test the access profile list casew…
jeremi Nov 10, 2026
bf045f7
docs(platform): say dev start refuses binding IDs the projects do not…
jeremi Nov 10, 2026
ed1b22c
fix(bregctl): locate dev encrypted-field refusals and match the BReg …
jeremi Nov 10, 2026
13a5ce5
test(bregctl): check the dev install hint without depending on which …
jeremi Nov 10, 2026
2ec1432
fix(bregctl): report the expiry dev tokens carry
jeremi Nov 10, 2026
44f4abd
fix(bregctl): refuse dev captures that refer to their own step
jeremi Nov 10, 2026
40a855b
fix(bregctl): require URI audiences for products a dev binding calls
jeremi Nov 10, 2026
749c31a
fix(bregctl): bound how long stop waits for the dev token server
jeremi Nov 10, 2026
019563b
test(bregctl): give the dev poll tests room on a busy machine
jeremi Nov 10, 2026
c99f843
fix(bregctl): check dev binding scopes against the OAuth limits
jeremi Nov 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/scripts/ci_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,9 @@
"docs/site/src/content/docs/configure/casework.mdx",
"docs/site/src/content/docs/operate/change-a-casework-package.mdx",
"docs/site/src/content/docs/tutorials/first-casework.mdx",
"products/breg/acceptance/reviewed-evidence-journey/**",
"products/platform/examples/licensing/**",
"products/platform/scripts/test-rstack-dev.py",
)

# Every input the Registry Messaging tutorial gate replays or is built from.
Expand Down Expand Up @@ -573,7 +576,7 @@
# reader makes carries a token that session issued. The clients in the Casework
# shard are not on the replayed path.
CASEWORK_TUTORIAL_PACKAGES = frozenset(
{"registry-casework", "registry-caseworkctl", "registry-breg", "registry-bregctl", "registry-thunderid-tooling"}
{"registry-casework", "registry-caseworkctl", "registry-breg", "registry-bregctl", "registry-rstack", "registry-thunderid-tooling"}
)

# The gate builds and runs exactly messagingctl, which links the Messaging
Expand Down
2 changes: 2 additions & 0 deletions .github/scripts/test_ci_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,8 @@ def test_casework_tutorial_routing(self) -> None:
"docs/site/scripts/tutorial-runner/toolsets.mjs",
"docs/site/src/content/docs/tutorials/first-casework.mdx",
"docs/site/package.json",
"products/platform/examples/licensing/dev.yaml",
"products/platform/scripts/test-rstack-dev.py",
)
for path in infrastructure:
with self.subTest(path=path):
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2697,6 +2697,26 @@ jobs:
-p registry-breg --features registry-breg/runtime \
-p registry-bregctl -p registry-rstack --bins

- name: Install native PostgreSQL 18 and PostGIS for project development
# The Ubuntu runner's PostgreSQL 16 is below BReg's minimum.
shell: bash
run: |
set -euo pipefail
sudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y
sudo env DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends postgresql-18 postgresql-18-postgis-3
/usr/lib/postgresql/18/bin/postgres --version

- name: Verify the combined licensing development run with native PostgreSQL
shell: bash
run: |
set -euo pipefail
cargo build --locked -p registry-rstack
python3 products/platform/scripts/test-rstack-dev.py \
--bin-dir "${GITHUB_WORKSPACE}/target/debug" \
--postgres-bin-dir /usr/lib/postgresql/18/bin \
--scratch-parent "${RUNNER_TEMP}" \
--spatial

- name: Execute the Registry Casework tutorials from a reader directory
shell: bash
env:
Expand Down
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ tempfile = { version = "3" }
thiserror = { version = "2" }
time = { version = "0.3", features = ["serde", "formatting", "parsing", "macros"] }
tokio = { version = "1", features = ["fs", "macros", "net", "rt", "rt-multi-thread", "signal", "sync", "time"] }
postgres-protocol = "=0.6.12"
tokio-postgres = { version = "=0.7.18", features = ["with-chrono-0_4", "with-serde_json-1", "with-uuid-1"] }
tokio-postgres-rustls = { version = "=0.14.0", default-features = false, features = ["ring", "native-certs"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12"] }
Expand Down
7 changes: 4 additions & 3 deletions crates/registry-bregctl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ hmac.workspace = true
inquire.workspace = true
jsonschema.workspace = true
p256.workspace = true
postgres-protocol.workspace = true
rcgen.workspace = true
registry-platform-canonical-json.workspace = true
registry-platform-config.workspace = true
Expand All @@ -69,6 +70,7 @@ registry-linkml.workspace = true
registry-manifest-core.workspace = true
reqwest.workspace = true
rustix.workspace = true
rustls.workspace = true
schemars = { workspace = true, optional = true }
serde.workspace = true
serde_json.workspace = true
Expand All @@ -79,6 +81,8 @@ tempfile.workspace = true
thiserror.workspace = true
time.workspace = true
tokio = { workspace = true, features = ["rt"] }
tokio-postgres.workspace = true
tokio-postgres-rustls.workspace = true
uuid = { workspace = true, features = ["serde"] }
zeroize.workspace = true
registry-platform-crypto.workspace = true
Expand All @@ -87,7 +91,4 @@ url.workspace = true
[dev-dependencies]
registry-breg.workspace = true
registry-platform-testing = { workspace = true, features = ["test-utils"] }
rustls.workspace = true
tokio-postgres.workspace = true
tokio-postgres-rustls.workspace = true
wat = "1.259.0"
52 changes: 32 additions & 20 deletions crates/registry-bregctl/src/identity_facts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,37 @@ impl<'a> Grant<'a> {
}
}

fn compiled_grants(compiled: &CompiledRegistry) -> impl Iterator<Item = Grant<'_>> {
let entity_grants = compiled
.entities()
.values()
.flat_map(|entity| entity.access_profiles.values().map(Grant::profile));
let dataset_grants = compiled
.statistical_datasets()
.values()
.flat_map(|dataset| dataset.access_profiles.values().map(Grant::profile));
let action_grants = compiled.actions().actions.iter().flat_map(|action| {
let proposal = match &action.execution {
CompiledActionExecution::Proposal { proposal } => proposal.permissions.as_slice(),
CompiledActionExecution::Immediate => &[],
};
action
.permissions
.iter()
.map(Grant::action)
.chain(proposal.iter().map(Grant::proposal))
});
entity_grants.chain(dataset_grants).chain(action_grants)
}

/// Clients the runtime must list even if no fixture mints tokens for them.
pub(crate) fn named_requester_clients(compiled: &CompiledRegistry) -> BTreeSet<String> {
compiled_grants(compiled)
.flat_map(|grant| grant.requester_clients)
.chain(compiled.recipients().clients().map(str::to_owned))
.collect()
}

/// The claims BReg refuses a token for a grant without, apart from the
/// subject every token carries and the reserved consent claims the engine
/// fills from the verified client.
Expand Down Expand Up @@ -286,26 +317,7 @@ pub(crate) fn facts(

let mut profiles: BTreeMap<String, FactsProfile> = BTreeMap::new();
let mut omitted_agent_profiles = BTreeSet::new();
let entity_grants = compiled
.entities()
.values()
.flat_map(|entity| entity.access_profiles.values().map(Grant::profile));
let dataset_grants = compiled
.statistical_datasets()
.values()
.flat_map(|dataset| dataset.access_profiles.values().map(Grant::profile));
let action_grants = compiled.actions().actions.iter().flat_map(|action| {
let proposal = match &action.execution {
CompiledActionExecution::Proposal { proposal } => proposal.permissions.as_slice(),
CompiledActionExecution::Immediate => &[],
};
action
.permissions
.iter()
.map(Grant::action)
.chain(proposal.iter().map(Grant::proposal))
});
for grant in entity_grants.chain(dataset_grants).chain(action_grants) {
for grant in compiled_grants(compiled) {
if grant.actor_kind == Some(ActorKindSource::Agent) {
omitted_agent_profiles.insert(grant.id.to_owned());
continue;
Expand Down
6 changes: 6 additions & 0 deletions crates/registry-bregctl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ mod instance_claim_lifecycle;
mod module_lock_patch;
mod package_inspection;
mod package_lifecycle;
mod project_dev;
mod proposal_retention;
mod reconcile_lifecycle;
mod report;
Expand Down Expand Up @@ -225,6 +226,8 @@ enum Command {
Examples(dev::examples::ExamplesArgs),
#[command(name = "__dev-supervisor", hide = true)]
DevSupervisor(dev::SupervisorArgs),
#[command(name = "project-dev", hide = true)]
ProjectDev(project_dev::Args),
/// Explain compiled model, access, route, or event inventories.
Explain(ExplainArgs),
/// Compare an authoring candidate with a rederived closed package.
Expand Down Expand Up @@ -2902,6 +2905,9 @@ where
}
};
}
Command::ProjectDev(args) => {
return ExitCode::from(project_dev::run(args, stdout, stderr));
}
Command::Init(args) => match (args.from, args.template.as_deref()) {
(None, None) => init(&args.destination),
(None, Some(id)) => starters::run(&args.destination, id),
Expand Down
Loading
Loading