gowalk-cicd 1.0.210 → 1.0.211

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/README.md CHANGED
@@ -1395,6 +1395,9 @@ Backend Deploy also offers `operation: network-diagnostics`, with an exact `diag
1395
1395
  It reports the owned bridge/IPAM, observed pool conflicts, UDP 500/4500 ownership, bound host identity and
1396
1396
  kernel/firewall facts in a closed v3 artifact for IPv4 and v4 for IPv6. The IPv6 result also distinguishes
1397
1397
  host and owned-gateway default-route and forwarding observations; actual external connectivity stays unverified.
1398
+ Its artifact also retains a separate `transport.json` with the SSH exit status and fixed failure signals,
1399
+ including an observed gate refusal, without private transport output. These observations do not establish the
1400
+ installed host reader or the reason its gate refused; the network result and refusal retain their existing meaning.
1398
1401
  The allocator stays retired; a completed read is never
1399
1402
  deployment, port reservation, globally unused address space or tunnel proof. Effective firewall ingress and
1400
1403
  unobserved capabilities remain unverified. The [trusted-host procedure](docs/BACKEND_SSH_GATE.md#owned-bridge-and-vpn-prerequisite-readback)
@@ -341,11 +341,12 @@ runs:
341
341
  run: |
342
342
  RESULT_DIR="$(mktemp -d "$RUNNER_TEMP/backend-network-diagnostics.XXXXXX")"
343
343
  echo "result=$RESULT_DIR/result.json" >> "$GITHUB_OUTPUT"
344
+ echo "transport=$RESULT_DIR/transport.json" >> "$GITHUB_OUTPUT"
344
345
  python3 "${{ github.action_path }}/network_diagnostics.py" \
345
346
  --app "$DIAGNOSTIC_APP" --service "$DIAGNOSTIC_SERVICE" --expected-build-sha "$DIAGNOSTIC_BUILD" \
346
347
  --network "$DIAGNOSTIC_NETWORK" --pool "$DIAGNOSTIC_POOL" --vpn-service "$DIAGNOSTIC_VPN_SERVICE" \
347
348
  --host "$DIAGNOSTIC_HOST" --user "$DIAGNOSTIC_USER" --provider "$DIAGNOSTIC_PROVIDER" \
348
- --output "$RESULT_DIR/result.json"
349
+ --output "$RESULT_DIR/result.json" --transport-output "$RESULT_DIR/transport.json"
349
350
 
350
351
  - name: Retain scoped backend network result
351
352
  if: always() && inputs.operation == 'network-diagnostics'
@@ -354,7 +355,9 @@ runs:
354
355
  NODE_OPTIONS: --require "${{ github.action_path }}/scripts/artifact_env.cjs"
355
356
  with:
356
357
  name: backend-network-diagnostics-${{ github.job }}-${{ github.run_attempt }}
357
- path: ${{ steps.network_diagnostics.outputs.result }}
358
+ path: |
359
+ ${{ steps.network_diagnostics.outputs.result }}
360
+ ${{ steps.network_diagnostics.outputs.transport }}
358
361
  if-no-files-found: error
359
362
 
360
363
  - name: Cleanup key
@@ -3,13 +3,15 @@ import argparse
3
3
  import json
4
4
  import re
5
5
  import shlex
6
+ import sys
6
7
  from pathlib import Path
7
8
 
8
9
  from identity_diagnostics import ReaderFailure, bounded, retain_result
9
10
  from network_projection import NetworkFailure, envelope, scope, validate
11
+ from runtime_diagnostics import transport_signals
10
12
 
11
13
 
12
- def local(args):
14
+ def local(args, transport=None):
13
15
  fields = (args.app, args.service, args.expected_build_sha, args.network, args.pool,
14
16
  args.vpn_service, args.host, args.provider)
15
17
  scope(*fields)
@@ -17,14 +19,17 @@ def local(args):
17
19
  raise NetworkFailure('invalid_scope')
18
20
  command = shlex.join(['gowalk-backend', 'network-diagnostics', *fields])
19
21
  try:
20
- status, raw = bounded(['ssh', '-T', '-i', str(Path.home() / '.ssh/backend_deploy'),
22
+ status, raw, errors = bounded(['ssh', '-T', '-i', str(Path.home() / '.ssh/backend_deploy'),
21
23
  '-o', 'IdentitiesOnly=yes', '-o', 'BatchMode=yes', '-o', 'StrictHostKeyChecking=yes',
22
24
  '-o', 'ConnectTimeout=10', '-o', 'ServerAliveInterval=5', '-o', 'ServerAliveCountMax=2',
23
- '-o', 'ClearAllForwardings=yes', args.user + '@' + args.host, command], seconds=120, with_status=True)
25
+ '-o', 'ClearAllForwardings=yes', args.user + '@' + args.host, command],
26
+ seconds=120, with_status=True, with_stderr=True)
24
27
  except ReaderFailure as error:
25
28
  raise NetworkFailure(error.code) from None
26
29
  except OSError:
27
30
  raise NetworkFailure('transport_failure') from None
31
+ if transport is not None:
32
+ transport.update(exit_status=status, signals=transport_signals(status, errors))
28
33
  if status not in (0, 1):
29
34
  raise NetworkFailure('transport_failure')
30
35
  if status == 1 and not raw.strip():
@@ -45,16 +50,24 @@ def main():
45
50
  for name, default in [('service', 'api'), ('network', 'default'), ('vpn-service', 'vpn'),
46
51
  ('provider', 'none'), ('user', 'root')]:
47
52
  parser.add_argument('--' + name, default=default)
53
+ parser.add_argument('--transport-output', help='Separate closed SSH observation receipt')
48
54
  args = parser.parse_args()
49
55
  fields = (args.app, args.service, args.expected_build_sha, args.network, args.pool,
50
56
  args.vpn_service, args.host, args.provider)
57
+ transport = {'schema': 'gowalk-cicd/backend-network-transport.v1', 'exit_status': None, 'signals': []}
51
58
  try:
52
- result = local(args)
59
+ result = local(args, transport)
53
60
  except Exception as error:
54
61
  result = envelope(*fields, failure=error.code if isinstance(error, NetworkFailure) else 'unclassified',
55
62
  reader_version=None)
56
63
  try:
57
64
  retain_result(args.output, result)
65
+ if args.transport_output:
66
+ retain_result(args.transport_output, transport)
67
+ status = 'unknown' if transport['exit_status'] is None else str(transport['exit_status'])
68
+ print('::notice title=backend_network_transport::schema=' + transport['schema']
69
+ + ' exit_status=' + status + ' signals=' + (','.join(transport['signals']) or 'none'),
70
+ file=sys.stderr)
58
71
  except ReaderFailure:
59
72
  result = envelope(*fields, failure='artifact_write_failed', reader_version=None)
60
73
  print(json.dumps(result, separators=(',', ':')))
@@ -123,6 +123,14 @@ released `network_readback.py`. It accepts no uploaded Python or app-mirror help
123
123
  alone cannot install this host operation: install the integrity-verified published runtime first. A missing
124
124
  host reader returns `network_reader_unavailable` with no host reader version; it is not a network verdict.
125
125
 
126
+ The same artifact retains `transport.json`, schema `gowalk-cicd/backend-network-transport.v1`, and emits the
127
+ brace-free `backend_network_transport` notice. It uses the runtime diagnostic's fixed `exit_status` and
128
+ `signals` vocabulary described above; no private stderr is retained. In particular, SSH exit 1 with empty
129
+ stdout still yields `network_reader_unavailable`, while the separate `gate_refused` signal records an observed
130
+ gate refusal without guessing its policy, ownership or installed-reader cause. An incomplete SSH exit remains
131
+ null, and unknown text supplies no signal. Neither this sidecar nor a workflow update proves host adoption or
132
+ authorizes a retry, permission change or transport bypass; the existing result schema and refusal remain unchanged.
133
+
126
134
  The closed `gowalk-cicd/backend-network-diagnostics.v3` IPv4 result, or `v4` for IPv6, is retained as
127
135
  `backend-network-diagnostics-<job>-<attempt>/result.json`. `ok: true` means the bounded read completed;
128
136
  it never means a VPN is provisioned, traffic is reachable, a pool is globally unused or a tunnel works.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gowalk-cicd",
3
- "version": "1.0.210",
3
+ "version": "1.0.211",
4
4
  "description": "Zero-config GitHub Actions delivery for iOS TestFlight and Android Google Play.",
5
5
  "type": "module",
6
6
  "bin": {