chore: bump product to 0.6.0; multi-owner startup warning
Phase 3.5 ships → product minor bump under pre-1.0 rules (any surface
bump triggers minor). Schema is now 6 (0006_users_authz.sql); API
remains 1 (additive endpoints + new credential type, no breaking
shape changes). docs/versioning.md updated.
main.rs gets warn_on_multi_owner_install() which fires once after
bootstrap when more than one active owner exists — points the
operator at PATCH /admin/admins/{id} for cleanup. Soft-fail on DB
error (does not block startup).
The api-test schema assertion was updated to expect 6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
16
Cargo.lock
generated
16
Cargo.lock
generated
@@ -1311,7 +1311,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||
|
||||
[[package]]
|
||||
name = "picloud"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@@ -1335,7 +1335,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-executor"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"picloud-executor-core",
|
||||
@@ -1347,7 +1347,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-executor-core"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"picloud-shared",
|
||||
@@ -1361,7 +1361,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-manager"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"picloud-manager-core",
|
||||
@@ -1373,7 +1373,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-manager-core"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"async-trait",
|
||||
@@ -1397,7 +1397,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-orchestrator"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"picloud-orchestrator-core",
|
||||
@@ -1409,7 +1409,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-orchestrator-core"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -1428,7 +1428,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "picloud-shared"
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"chrono",
|
||||
|
||||
@@ -12,7 +12,7 @@ members = [
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.5.1"
|
||||
version = "0.6.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.92"
|
||||
license = "MIT OR Apache-2.0"
|
||||
|
||||
@@ -45,6 +45,7 @@ async fn run_server() -> anyhow::Result<()> {
|
||||
|
||||
let auth = AuthDeps::from_pool(pool.clone());
|
||||
bootstrap_first_admin(&*auth.users).await?;
|
||||
warn_on_multi_owner_install(&*auth.users).await;
|
||||
|
||||
// Seed Hello World into the default app when this is a fresh
|
||||
// install (no scripts and no routes). Idempotent on upgrades.
|
||||
@@ -79,6 +80,31 @@ async fn run_server() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Multi-owner startup warning — Phase 3.5 migration upgraded every
|
||||
/// pre-existing admin_users row to `Owner` via DEFAULT, which for
|
||||
/// installs with several Phase 3a admins means several co-owners.
|
||||
/// Surface this once at boot so the operator can demote extras via
|
||||
/// `PATCH /api/v1/admin/admins/{id}` with `instance_role: "admin"`.
|
||||
/// Soft-fail: a DB blip should not block startup.
|
||||
async fn warn_on_multi_owner_install(users: &dyn AdminUserRepository) {
|
||||
match users.list_active_owners().await {
|
||||
Ok(owners) if owners.len() > 1 => {
|
||||
let names: Vec<String> = owners.into_iter().map(|u| u.username).collect();
|
||||
tracing::warn!(
|
||||
count = names.len(),
|
||||
owners = ?names,
|
||||
"multiple active owners detected — Phase 3.5 promoted every \
|
||||
pre-existing admin to owner. Demote extras via \
|
||||
PATCH /api/v1/admin/admins/{{id}} with instance_role."
|
||||
);
|
||||
}
|
||||
Ok(_) => {}
|
||||
Err(err) => {
|
||||
tracing::warn!(?err, "could not count active owners for multi-owner startup check");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_session_pruner(sessions: Arc<dyn AdminSessionRepository>) {
|
||||
tokio::spawn(async move {
|
||||
let mut ticker = tokio::time::interval(Duration::from_secs(600));
|
||||
|
||||
@@ -822,7 +822,7 @@ async fn version_includes_public_base_url(pool: PgPool) {
|
||||
let v: Value = r.json();
|
||||
assert!(v["public_base_url"].is_string());
|
||||
assert_eq!(v["api"], 1);
|
||||
assert_eq!(v["schema"], 5);
|
||||
assert_eq!(v["schema"], 6);
|
||||
assert_eq!(v["sdk"], "1.1");
|
||||
}
|
||||
|
||||
|
||||
4
dashboard/package-lock.json
generated
4
dashboard/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "picloud-dashboard",
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "picloud-dashboard",
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.0",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.20.2",
|
||||
"@codemirror/commands": "^6.10.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "picloud-dashboard",
|
||||
"version": "0.5.1",
|
||||
"version": "0.6.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -126,10 +126,10 @@ A surface can hit its own `1.0` independently of the product. The SDK in particu
|
||||
|
||||
| | Version |
|
||||
|---|---|
|
||||
| Product | `0.5.1` |
|
||||
| Product | `0.6.0` |
|
||||
| SDK | `1.1` (adds `ctx.request.params`, `ctx.request.query`, `ctx.request.rest`) |
|
||||
| API | `1` (additive: `Script.app_id`, `Route.app_id`, `ExecutionLog.app_id`, new `/api/v1/admin/apps/*` endpoints, `?app=` filter on script list) |
|
||||
| Schema | `5` (matches `migrations/0005_apps.sql`) |
|
||||
| API | `1` (additive: `Script.app_id`, `Route.app_id`, `ExecutionLog.app_id`, new `/api/v1/admin/apps/*` and `/api/v1/admin/api-keys/*` endpoints, `?app=` filter on script list, `Authorization: Bearer pic_…` credential type, 403 responses on previously-401-only admin endpoints when the caller lacks the required capability) |
|
||||
| Schema | `6` (matches `migrations/0006_users_authz.sql`) |
|
||||
| Wire | `1` (reserved; cluster mode not implemented) |
|
||||
|
||||
Read live from `GET /version` on any running instance.
|
||||
|
||||
Reference in New Issue
Block a user