Experiment formal custody reader source plan 03 - kmosoti/FabricO11y GitHub Wiki
custody reader source plan 03
Prospective: NOT RUN. Clean head 158a5ec1129e6a9789b3d4271cea0020fecd6ff6.
C-083 admitted the literal prefix red at trust609368a; exactly one ValueError-not-raised failure was preserved at wiki93df129. Separate production158a changes only the reader +30/-22:417total/+120over297. Prefix rows tile every archived final-cursor path exactly, checking body/newline/device/inode; validated record maps are reused for projection. All controls/protocol/oracles remain unchanged. Full install discovery includes the17 custody methods and all existing checker/pressure/continuation methods (expected30total). Candidate bindings/native guest producer remain pending; no raw server storage authentication is claimed.
Root runs four exact serial source cells. Every cell uses the driver, resource_group, a fresh full DATA namespace census, full1GiB reserve,95GB admission including reserve/100GB ceiling,16GiB memory high/20GiBmax/no swap/1800seconds. Dirty/moved source or any project workload refuses admission. Any unexpected failure stops this sequence; retain failures and report exact command/exit/stop. Inspect cleanup and read #59 after each cell. Existing Bun1.4.0/106 individual ignored locked dependency links/cache are reused without installation. No VM, installation, native browser, simulator, Rust/C compile, smoke or FULL is launched.
Pins
/run/media/kmosoti/data/FabricO11y/results/candidate-build-fresh-8fb6f413179b-01/run-step-custody-reader-source-03.pySHA-256edb3ae6c01fede61324907c917825dd1721b0e37b46bbdadf396cb6c968a3e65./run/media/kmosoti/data/FabricO11y/scratch/installation-custody-witness/tools/qualification/install/custody_witness.pySHA-2562c500203cc26a474366d4b9daf13d63332fb6454fc94649a00f8dd43eb796ebf./run/media/kmosoti/data/FabricO11y/scratch/installation-custody-witness/tools/qualification/install/test_custody_witness.pySHA-256fa4782a9ff25e72d91546207681db8e9f96c4b771472bbbcacb60b41f85c4a61./run/media/kmosoti/data/FabricO11y/scratch/installation-custody-witness/docs/experiments/formal/installation-release-protocol.mdSHA-256cec645a8f5f029b828526b852385fd411452480a067fbcf0c746499d0d49cd3d.
Exact commands
python3 -B /run/media/kmosoti/data/FabricO11y/results/candidate-build-fresh-8fb6f413179b-01/run-step-custody-reader-source-03.py installation-custody-source-controls-03 1073741824 python3 -B -m unittest discover -s tools/qualification/install -p 'test_*.py' -v
python3 -B /run/media/kmosoti/data/FabricO11y/results/candidate-build-fresh-8fb6f413179b-01/run-step-custody-reader-source-03.py installation-custody-docs-check-03 1073741824 env PATH=/run/media/kmosoti/data/FabricO11y/tools/bun-1.4.0:/usr/local/bin:/usr/bin:/bin BUN_INSTALL_CACHE_DIR=/run/media/kmosoti/data/FabricO11y/tools/docs-bun-cache /run/media/kmosoti/data/FabricO11y/tools/bun-1.4.0/bun tools/docs/check.mjs
python3 -B /run/media/kmosoti/data/FabricO11y/results/candidate-build-fresh-8fb6f413179b-01/run-step-custody-reader-source-03.py installation-custody-docs-tests-03 1073741824 env PATH=/run/media/kmosoti/data/FabricO11y/tools/bun-1.4.0:/usr/local/bin:/usr/bin:/bin BUN_INSTALL_CACHE_DIR=/run/media/kmosoti/data/FabricO11y/tools/docs-bun-cache /run/media/kmosoti/data/FabricO11y/tools/bun-1.4.0/bun tools/docs/check.test.mjs
python3 -B /run/media/kmosoti/data/FabricO11y/results/candidate-build-fresh-8fb6f413179b-01/run-step-custody-reader-source-03.py installation-custody-docs-hooks-03 1073741824 env PATH=/run/media/kmosoti/data/FabricO11y/tools/bun-1.4.0:/usr/local/bin:/usr/bin:/bin BUN_INSTALL_CACHE_DIR=/run/media/kmosoti/data/FabricO11y/tools/docs-bun-cache python3 -B tools/docs/test_hooks.py
Full production delta
diff --git a/tools/qualification/install/custody_witness.py b/tools/qualification/install/custody_witness.py
index 6db3fce..16831f0 100644
--- a/tools/qualification/install/custody_witness.py
+++ b/tools/qualification/install/custody_witness.py
@@ -106,16 +106,18 @@ def fields(raw, types, depth=0):
def validate(raw, schema, depth=0):
- types = SCHEMAS[schema]
- for number, values in fields(raw, types, depth).items():
- spec = types.get(number)
+ parsed = fields(raw, SCHEMAS[schema], depth)
+ records = [parsed] if schema == 'record' else []
+ for number, values in parsed.items():
+ spec = SCHEMAS[schema].get(number)
if isinstance(spec, str):
for _, value in values:
if spec == 'utf8':
value.decode('utf-8')
else:
require(depth < 100, 'protobuf message recursion depth exhausted')
- validate(value, spec, depth + 1)
+ records.extend(validate(value, spec, depth + 1))
+ return records
def one(values, number, default=0):
@@ -136,21 +138,16 @@ def string_projection(values):
return length_field(1, one(f, 1, b'')) if active == 1 else b''
-def log_rows(raw, batch):
- index = 0
- for _, resource in fields(raw, SCHEMAS['logs']).get(1, []):
- for _, scope in fields(resource, SCHEMAS['resource_logs']).get(2, []):
- for _, record in fields(scope, SCHEMAS['scope_logs']).get(2, []):
- f = fields(record, SCHEMAS['record'])
- projection = [b'\x59' + one(f, 11, b'\0' * 8), length_field(5, string_projection(f.get(5, [])))]
- for _, attribute in f.get(6, []):
- kv = fields(attribute, SCHEMAS['kv'])
- projection.append(length_field(6, length_field(1, one(kv, 1, b''))
- + length_field(2, string_projection(kv.get(2, [])))))
- row = oracle.decode_log_record(b''.join(projection))
- yield dict(node='spindle-1', node_id=batch['node_id'].hex(), sequence=batch['sequence'],
- index=index, observed_ns=row['observed_time_unix_nano'], body=row['body'], attributes=row['attributes'])
- index += 1
+def log_rows(records, batch):
+ for index, f in enumerate(records):
+ projection = [b'\x59' + one(f, 11, b'\0' * 8), length_field(5, string_projection(f.get(5, [])))]
+ for _, attribute in f.get(6, []):
+ kv = fields(attribute, SCHEMAS['kv'])
+ projection.append(length_field(6, length_field(1, one(kv, 1, b''))
+ + length_field(2, string_projection(kv.get(2, [])))))
+ row = oracle.decode_log_record(b''.join(projection))
+ yield dict(node='spindle-1', node_id=batch['node_id'].hex(), sequence=batch['sequence'],
+ index=index, observed_ns=row['observed_time_unix_nano'], body=row['body'], attributes=row['attributes'])
def cursor(raw):
@@ -185,9 +182,8 @@ def envelope(raw):
gap.decode('utf-8')
cursors = [cursor(value) for _, value in f.get(7, [])]
batch = dict(version=one(f, 1), node_id=one(f, 2, b''), generation=one(f, 3), sequence=one(f, 4))
- for signal, schema in zip(signals, ('metrics', 'logs', 'traces')):
- validate(signal, schema)
- rows = list(log_rows(signals[1], batch))
+ decoded = [validate(signal, schema) for signal, schema in zip(signals, ('metrics', 'logs', 'traces'))]
+ rows = list(log_rows(decoded[1], batch))
return batch, cursors, rows
except (oracle.MalformedInput, UnicodeError, TypeError, struct.error) as error:
raise ValueError(str(error)) from error
@@ -379,6 +375,18 @@ def conserve(before, after_install, after_drain, queries, candidate_ack_events):
and not any(row['body'] in (queries['pending_body'], queries['unread_body']) for row in old), 'invalid old-row baseline')
expected = old + [pending_row, unread_row]
require(all(row in old + [pending_row] for source in pending for row in source['rows']), 'unexpected pending log row')
+ for path, current in after_drain['cursors'].items():
+ log, offset = after_drain['logs'][path], 0
+ for row in sorted((row for row in expected if row['attributes'].get('log.file.path') == path),
+ key=lambda row: int(row['attributes']['log.file.offset.start'])):
+ attrs = row['attributes']
+ start, end = (int(attrs[key]) for key in ('log.file.offset.start', 'log.file.offset.end'))
+ require(start == offset and start < end <= current['offset']
+ and log['bytes'][start:end] == (row['body'] + '\n').encode()
+ and attrs['log.file.device'] == str(log['device']) and attrs['log.file.inode'] == str(log['inode']),
+ 'source prefix conservation')
+ offset = end
+ require(offset == current['offset'], 'source prefix conservation')
keys = lambda rows: sorted((row['node_id'], row['sequence'], row['index']) for row in rows)
encoded = lambda rows: sorted(json.dumps(row, sort_keys=True, allow_nan=False) for row in rows)
require(len(set(keys(expected))) == len(expected), 'duplicate expected identity')