@mriekki/project-forge 4.22.0 → 4.22.1

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@mriekki/project-forge",
4
- "version": "4.22.0",
4
+ "version": "4.22.1",
5
5
  "defaultProfile": "greenfield-project",
6
6
  "profiles": {
7
7
  "greenfield-project": {
@@ -21,7 +21,7 @@
21
21
  "canonicalDescriptor": "distributions/greenfield-workspace.json"
22
22
  },
23
23
  "deployment": {
24
- "revision": "2258794181483747ed11a2c3c3226d6e66e1b9bb",
24
+ "revision": "39fbd69e7b81a93929f60d107dac18bb3f1c675c",
25
25
  "distribution": "greenfield-project",
26
26
  "descriptor": "assets/deployment/distribution.json",
27
27
  "sourceRoot": "assets/generated/deployment",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@mriekki/project-forge",
4
- "version": "4.22.0",
4
+ "version": "4.22.1",
5
5
  "components": {
6
6
  "core": {
7
7
  "revision": "4c74c1801b82d3aa438447d392024d32ca5697b0",
@@ -361,7 +361,7 @@
361
361
  ]
362
362
  },
363
363
  "deployment": {
364
- "revision": "2258794181483747ed11a2c3c3226d6e66e1b9bb",
364
+ "revision": "39fbd69e7b81a93929f60d107dac18bb3f1c675c",
365
365
  "distribution": "greenfield-project",
366
366
  "files": [
367
367
  {
@@ -442,7 +442,7 @@
442
442
  {
443
443
  "source": "src/project_forge_deployment/cloudflare_ingress_remote.py",
444
444
  "destination": "tools/project-forge-deployment/project_forge_deployment/cloudflare_ingress_remote.py",
445
- "sha256": "19de0d8c04b7ad0006b8bc341eabd52a5eaa50c0e0bacdc9edb856de101dd259"
445
+ "sha256": "665fe9aa209d3caa81332a7a4291159900ca457339c64dcd05169dfe35e8dc67"
446
446
  },
447
447
  {
448
448
  "source": "src/project_forge_deployment/cloudflare_route_apply.py",
@@ -56,6 +56,23 @@ marker_value() {
56
56
  sed -n "s/^${key}=//p" "$MARKER" | head -n1
57
57
  }
58
58
 
59
+ # Legacy markers can predate AUTHENTICATED_ORIGIN; an empty explicit value
60
+ # or any other invalid mode must not be treated as an absent key.
61
+ legacy_origin_mode() {
62
+ local mode
63
+ [[ -f "$MARKER" && ! -L "$MARKER" ]] || return 1
64
+ mode="$(marker_value AUTHENTICATED_ORIGIN 2>/dev/null || true)"
65
+ [[ "$mode" == false ]] && return 0
66
+ [[ -z "$mode" ]] && ! grep -q '^AUTHENTICATED_ORIGIN=' "$MARKER"
67
+ }
68
+
69
+ # The pinned root-run Caddy listener creates the Unix socket (0:0:0222).
70
+ # cloudflared owns the containing 0700 directory, not the socket.
71
+ auth_socket_metadata_valid() {
72
+ [[ -S "$AUTH_SOCKET" && ! -L "$AUTH_SOCKET" &&
73
+ "$(stat -c '%u:%g:%a' "$AUTH_SOCKET")" == "0:0:222" ]]
74
+ }
75
+
59
76
  platform_ready() {
60
77
  [[ "$(docker inspect --format '{{.State.Status}}' "$CADDY_CONTAINER" 2>/dev/null || true)" == "running" ]] &&
61
78
  docker network inspect "$NETWORK_NAME" >/dev/null 2>&1
@@ -424,7 +441,7 @@ migration_inspect() {
424
441
  echo "Authenticated-origin migration recovery evidence is incomplete or changed." >&2
425
442
  exit 37
426
443
  fi
427
- elif [[ "$mode" == false && ! -e "$MIGRATION_MARKER_BACKUP" &&
444
+ elif legacy_origin_mode && [[ ! -e "$MIGRATION_MARKER_BACKUP" &&
428
445
  ! -e "$MIGRATION_COMPOSE_BACKUP" && ! -e "$MIGRATION_RECEIPT" &&
429
446
  ! -e "$AUTH_ROOT" && ! -e "$AUTH_CADDY" ]]; then
430
447
  state=clean
@@ -469,7 +486,7 @@ migration_rollback_on_error() {
469
486
  fi
470
487
  done
471
488
  if [[ -e "$AUTH_SOCKET" ]]; then
472
- if [[ -S "$AUTH_SOCKET" && "$(stat -c '%u:%g:%a' "$AUTH_SOCKET")" == "65532:65532:222" ]]; then
489
+ if auth_socket_metadata_valid; then
473
490
  rm -f "$AUTH_SOCKET"
474
491
  else
475
492
  rollback_failed=true
@@ -489,8 +506,8 @@ migration_rollback_on_error() {
489
506
  migrate_authenticated_origin() {
490
507
  local expected_route_digest="$EXPECTED" state path route_spec
491
508
  [[ "$AUTHENTICATED_ORIGIN" == true ]] || { echo "Authenticated-origin migration must opt in explicitly." >&2; exit 37; }
492
- [[ "$(status | sed -n 's/^state=//p' | head -n1)" == ready &&
493
- "$(marker_value AUTHENTICATED_ORIGIN 2>/dev/null || true)" == false ]] || {
509
+ [[ "$(status | sed -n 's/^state=//p' | head -n1)" == ready ]] &&
510
+ legacy_origin_mode || {
494
511
  echo "Authenticated-origin migration requires a ready legacy scope." >&2; exit 37;
495
512
  }
496
513
  [[ "$(route_inventory_digest)" == "$expected_route_digest" ]] || {
@@ -568,8 +585,8 @@ rollback_authenticated_origin() {
568
585
  cp -p "$MIGRATION_COMPOSE_BACKUP" "$COMPOSE_FILE.rollback.$$"
569
586
  mv -f "$COMPOSE_FILE.rollback.$$" "$COMPOSE_FILE"
570
587
  docker compose -f "$COMPOSE_FILE" up -d --force-recreate >/dev/null
571
- [[ "$(status | sed -n 's/^state=//p' | head -n1)" == ready &&
572
- "$(marker_value AUTHENTICATED_ORIGIN 2>/dev/null || true)" == false ]] || {
588
+ [[ "$(status | sed -n 's/^state=//p' | head -n1)" == ready ]] &&
589
+ legacy_origin_mode || {
573
590
  echo "Legacy connector did not become ready after authenticated-origin rollback." >&2; exit 38;
574
591
  }
575
592
  [[ -f "$AUTH_CADDY" && ! -L "$AUTH_CADDY" ]] || {
@@ -579,7 +596,7 @@ rollback_authenticated_origin() {
579
596
  docker exec "$CADDY_CONTAINER" caddy reload --config /etc/caddy/Caddyfile >/dev/null
580
597
  for path in "$AUTH_ROUTES"/*.caddy; do [[ -f "$path" ]] && rm -f "$path"; done
581
598
  if [[ -e "$AUTH_SOCKET" ]]; then
582
- [[ -S "$AUTH_SOCKET" && "$(stat -c '%u:%g:%a' "$AUTH_SOCKET")" == "65532:65532:222" ]] || {
599
+ auth_socket_metadata_valid || {
583
600
  echo "Authenticated origin socket changed before rollback." >&2; exit 38;
584
601
  }
585
602
  rm -f "$AUTH_SOCKET"
@@ -602,9 +619,9 @@ verify_authenticated_origin() {
602
619
  local expected_route_digest="$EXPECTED" path route_spec
603
620
  [[ "$(status | sed -n 's/^state=//p' | head -n1)" == ready &&
604
621
  "$(marker_value AUTHENTICATED_ORIGIN 2>/dev/null || true)" == true &&
605
- -S "$AUTH_SOCKET" && -d "$AUTH_ROOT" && ! -L "$AUTH_ROOT" &&
606
- "$(stat -c '%u:%g:%a' "$AUTH_ROOT")" == "65532:65532:700" &&
607
- "$(stat -c '%u:%g:%a' "$AUTH_SOCKET")" == "65532:65532:222" ]] || {
622
+ -d "$AUTH_ROOT" && ! -L "$AUTH_ROOT" &&
623
+ "$(stat -c '%u:%g:%a' "$AUTH_ROOT")" == "65532:65532:700" ]] &&
624
+ auth_socket_metadata_valid || {
608
625
  echo "Authenticated-origin socket or scope is not ready." >&2; exit 40;
609
626
  }
610
627
  [[ "$(route_inventory_digest)" == "$expected_route_digest" ]] || {
@@ -615,6 +632,7 @@ verify_authenticated_origin() {
615
632
  }
616
633
  path_overlap() {
617
634
  local left="${1%/}" right="${2%/}"
635
+ [[ -n "$left" && -n "$right" ]] || return 1
618
636
  [[ "$left" == "$right" || "$left" == "$right/"* || "$right" == "$left/"* ]]
619
637
  }
620
638
  local connector_id caddy_id mount_count other_id mounts source destination writable source_mount
@@ -623,6 +641,7 @@ verify_authenticated_origin() {
623
641
  mapfile -t mounts < <(docker inspect --format '{{range .Mounts}}{{printf "%s|%s|%t\n" .Source .Destination .RW}}{{end}}' "$CONTAINER")
624
642
  mount_count=0
625
643
  for source_mount in "${mounts[@]}"; do
644
+ [[ -n "$source_mount" ]] || continue
626
645
  IFS='|' read -r source destination writable <<< "$source_mount"
627
646
  if path_overlap "$source" "$AUTH_ROOT" || path_overlap "$destination" "/run/project-forge-origin"; then
628
647
  [[ "$source" == "$AUTH_ROOT" && "$destination" == "/run/project-forge-origin" &&
@@ -639,6 +658,7 @@ verify_authenticated_origin() {
639
658
  [[ -n "$other_id" && "$other_id" != "$connector_id" && "$other_id" != "$caddy_id" ]] || continue
640
659
  mapfile -t mounts < <(docker inspect --format '{{range .Mounts}}{{printf "%s|%s\n" .Source .Destination}}{{end}}' "$other_id")
641
660
  for source_mount in "${mounts[@]}"; do
661
+ [[ -n "$source_mount" ]] || continue
642
662
  IFS='|' read -r source destination <<< "$source_mount"
643
663
  if path_overlap "$source" "$AUTH_ROOT" ||
644
664
  path_overlap "$destination" "/run/project-forge-origin"; then
@@ -646,7 +666,7 @@ verify_authenticated_origin() {
646
666
  exit 40
647
667
  fi
648
668
  done
649
- done < <(docker ps -aq)
669
+ done < <(docker ps -aq --no-trunc)
650
670
  [[ -f "$AUTH_CADDY" && ! -L "$AUTH_CADDY" ]] &&
651
671
  grep -Fqx " bind unix//data/authenticated/$SCOPE/origin.sock|0222" "$AUTH_CADDY" &&
652
672
  grep -Fqx " import /data/authenticated/$SCOPE/routes/*.caddy" "$AUTH_CADDY" || {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mriekki/project-forge",
3
- "version": "4.22.0",
3
+ "version": "4.22.1",
4
4
  "description": "Public consumer distribution and updater for Project Forge engineering assets.",
5
5
  "type": "module",
6
6
  "bin": {