agentsor-file 0.2.0__tar.gz
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.
- agentsor_file-0.2.0/LICENSE +21 -0
- agentsor_file-0.2.0/PKG-INFO +247 -0
- agentsor_file-0.2.0/README.md +218 -0
- agentsor_file-0.2.0/pyproject.toml +53 -0
- agentsor_file-0.2.0/setup.cfg +4 -0
- agentsor_file-0.2.0/src/agentsor_file.egg-info/PKG-INFO +247 -0
- agentsor_file-0.2.0/src/agentsor_file.egg-info/SOURCES.txt +24 -0
- agentsor_file-0.2.0/src/agentsor_file.egg-info/dependency_links.txt +1 -0
- agentsor_file-0.2.0/src/agentsor_file.egg-info/entry_points.txt +3 -0
- agentsor_file-0.2.0/src/agentsor_file.egg-info/requires.txt +7 -0
- agentsor_file-0.2.0/src/agentsor_file.egg-info/top_level.txt +1 -0
- agentsor_file-0.2.0/src/parquet_guard/__init__.py +28 -0
- agentsor_file-0.2.0/src/parquet_guard/cli.py +75 -0
- agentsor_file-0.2.0/src/parquet_guard/config.py +176 -0
- agentsor_file-0.2.0/src/parquet_guard/contracts.py +256 -0
- agentsor_file-0.2.0/src/parquet_guard/file_cli.py +279 -0
- agentsor_file-0.2.0/src/parquet_guard/file_contracts.py +685 -0
- agentsor_file-0.2.0/src/parquet_guard/fingerprints.py +50 -0
- agentsor_file-0.2.0/src/parquet_guard/hosted.py +485 -0
- agentsor_file-0.2.0/src/parquet_guard/pipeline.py +425 -0
- agentsor_file-0.2.0/src/parquet_guard/py.typed +1 -0
- agentsor_file-0.2.0/src/parquet_guard/schemas/error-envelope-v1.schema.json +38 -0
- agentsor_file-0.2.0/src/parquet_guard/schemas/result-envelope-v1.schema.json +255 -0
- agentsor_file-0.2.0/tests/test_file_contracts.py +781 -0
- agentsor_file-0.2.0/tests/test_hosted.py +262 -0
- agentsor_file-0.2.0/tests/test_pipeline.py +362 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agentsor
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentsor-file
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local CSV and Parquet contracts with redacted hosted receipts
|
|
5
|
+
Author: Agentsor
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://agentsor.ai/file-contracts
|
|
8
|
+
Project-URL: Repository, https://github.com/linkoinsight/agentsor-file
|
|
9
|
+
Project-URL: Issues, https://github.com/linkoinsight/agentsor-file/issues
|
|
10
|
+
Keywords: csv,parquet,data-contracts,schema-validation
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: pyarrow<24,>=16
|
|
23
|
+
Provides-Extra: dev
|
|
24
|
+
Requires-Dist: build<2,>=1.2; extra == "dev"
|
|
25
|
+
Requires-Dist: jsonschema<5,>=4.23; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest<10,>=8; extra == "dev"
|
|
27
|
+
Requires-Dist: ruff<0.14,>=0.12; extra == "dev"
|
|
28
|
+
Dynamic: license-file
|
|
29
|
+
|
|
30
|
+
# Agentsor File Contracts
|
|
31
|
+
|
|
32
|
+
Agentsor File Contracts is a free, MIT-licensed command-line tool for checking
|
|
33
|
+
one local CSV or Parquet file against an explicit TOML contract. It checks:
|
|
34
|
+
|
|
35
|
+
- file readability;
|
|
36
|
+
- required columns and Arrow types;
|
|
37
|
+
- unexpected columns;
|
|
38
|
+
- row and byte bounds;
|
|
39
|
+
- optional event-time freshness; and
|
|
40
|
+
- optional duplicate history.
|
|
41
|
+
|
|
42
|
+
`init`, `check`, and `schema` run offline. The separate `report` command checks
|
|
43
|
+
the file locally and sends only the fixed redacted result envelope to the
|
|
44
|
+
single Agentsor collector. The package has no file-upload or telemetry path.
|
|
45
|
+
|
|
46
|
+
## Local quickstart
|
|
47
|
+
|
|
48
|
+
Python 3.11 or newer is required. From this checkout:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
python -m venv .venv
|
|
52
|
+
. .venv/bin/activate
|
|
53
|
+
python -m pip install .
|
|
54
|
+
agentsor-file init \
|
|
55
|
+
--format parquet \
|
|
56
|
+
--contract file-contract.toml \
|
|
57
|
+
--fingerprint-key-file .agentsor-file.key
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
`init` refuses to replace either target or follow a target symlink. It creates
|
|
61
|
+
a random 32-byte fingerprint key with mode `0600` and never prints the key.
|
|
62
|
+
Edit the generated `[schema]` table to describe the file, then run:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
agentsor-file check YOUR_FILE.parquet \
|
|
66
|
+
--contract file-contract.toml \
|
|
67
|
+
--fingerprint-key-file .agentsor-file.key \
|
|
68
|
+
--state .agentsor-file-state.json
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The `init`, `check`, and `schema` commands make no network requests. The CLI
|
|
72
|
+
requires the fingerprint key to be an owner-only regular file and refuses
|
|
73
|
+
links or group/world-readable modes. Keep it private and stable within one
|
|
74
|
+
project. Back it up if fingerprint continuity matters.
|
|
75
|
+
|
|
76
|
+
The CLI exits `0` for a passed contract, `1` for a failed or inconclusive
|
|
77
|
+
result, and `2` for a usage, contract, credential, input, transport, or hosted
|
|
78
|
+
receipt error.
|
|
79
|
+
|
|
80
|
+
## Hosted deadline reporting
|
|
81
|
+
|
|
82
|
+
After creating a free monitor at
|
|
83
|
+
[agentsor.ai/file-contracts](https://agentsor.ai/file-contracts), put the
|
|
84
|
+
one-time ingest token in an owner-only credential file without placing it in a
|
|
85
|
+
shell argument:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
mkdir -m 700 -p ~/.config/agentsor
|
|
89
|
+
umask 077
|
|
90
|
+
${EDITOR:-vi} ~/.config/agentsor/file-token
|
|
91
|
+
chmod 600 ~/.config/agentsor/file-token
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Then check and submit one redacted result:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
agentsor-file report YOUR_FILE.parquet \
|
|
98
|
+
--contract file-contract.toml \
|
|
99
|
+
--fingerprint-key-file .agentsor-file.key \
|
|
100
|
+
--token-file ~/.config/agentsor/file-token
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`report` has a fixed HTTPS destination, disables inherited proxies and
|
|
104
|
+
redirects, verifies TLS, bounds request/response sizes, validates the complete
|
|
105
|
+
result before network I/O, and never prints the token. It prints a fixed
|
|
106
|
+
acknowledgement containing the run ID, local overall result, duplicate-receipt
|
|
107
|
+
flag, and next hosted deadline.
|
|
108
|
+
|
|
109
|
+
Hosted reporting does not currently accept `--state`; configure
|
|
110
|
+
`reject_duplicates = false` for that command. Use offline `check --state` when
|
|
111
|
+
local duplicate-output detection is required. This avoids mutating duplicate
|
|
112
|
+
state before a network failure can be retried safely.
|
|
113
|
+
|
|
114
|
+
## Contract format
|
|
115
|
+
|
|
116
|
+
```toml
|
|
117
|
+
[contract]
|
|
118
|
+
format = "parquet"
|
|
119
|
+
allow_extra_columns = false
|
|
120
|
+
min_rows = 1
|
|
121
|
+
max_rows = 1000000
|
|
122
|
+
min_bytes = 1
|
|
123
|
+
max_bytes = 104857600
|
|
124
|
+
csv_delimiter = ","
|
|
125
|
+
reject_duplicates = false
|
|
126
|
+
|
|
127
|
+
# Optional; configure both together.
|
|
128
|
+
# event_time_column = "event_time"
|
|
129
|
+
# max_age_seconds = 86400
|
|
130
|
+
|
|
131
|
+
[schema]
|
|
132
|
+
id = "string"
|
|
133
|
+
amount = "double"
|
|
134
|
+
# event_time = "timestamp[ms]"
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`format` may be `csv` or `parquet`, or omitted when one contract intentionally
|
|
138
|
+
supports both. Schema values use PyArrow type aliases. Parquet physical types
|
|
139
|
+
must match exactly. CSV has no physical type metadata, so required CSV columns
|
|
140
|
+
must safely cast to their configured Arrow types.
|
|
141
|
+
|
|
142
|
+
Freshness uses the newest non-null event time. Timestamp columns without a
|
|
143
|
+
timezone are interpreted as UTC. `reject_duplicates = true` requires
|
|
144
|
+
`--state`; without usable state, the result is inconclusive. State contains
|
|
145
|
+
only project-keyed output fingerprints and retains the latest 4,096 unique
|
|
146
|
+
values.
|
|
147
|
+
|
|
148
|
+
## Redacted result envelope
|
|
149
|
+
|
|
150
|
+
`check` writes exactly one JSON object to stdout. The v1 envelope contains a
|
|
151
|
+
canonical run UUID and UTC timestamps, format, bounded row/byte counts, six
|
|
152
|
+
fixed check statuses, fixed reason codes, and three fingerprints. It does not
|
|
153
|
+
contain file paths, file names, column names, raw values, exception messages,
|
|
154
|
+
or arbitrary text.
|
|
155
|
+
|
|
156
|
+
The contract, schema, and output fingerprints are domain-separated
|
|
157
|
+
HMAC-SHA256 values keyed by the supplied project key. They support equality
|
|
158
|
+
and drift checks inside that project without exposing a global raw SHA-256
|
|
159
|
+
that could correlate low-entropy files or schemas across projects.
|
|
160
|
+
|
|
161
|
+
Redaction is not zero knowledge: row/byte counts, timing, outcomes, and
|
|
162
|
+
within-project equality can still reveal metadata. Review that boundary
|
|
163
|
+
before sharing a result.
|
|
164
|
+
|
|
165
|
+
Print the installed formal JSON Schema with:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
agentsor-file schema
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The fixed checks are `readability`, `schema`, `rowBounds`, `byteBounds`,
|
|
172
|
+
`eventFreshness`, and `duplicate`. Required checks use
|
|
173
|
+
`passed|failed|inconclusive`; the two optional checks may also use
|
|
174
|
+
`not_configured`. Overall status is:
|
|
175
|
+
|
|
176
|
+
- `passed` when every check is passed or not configured and reasons are empty;
|
|
177
|
+
- `failed` when at least one check failed; or
|
|
178
|
+
- `inconclusive` when none failed and at least one could not complete.
|
|
179
|
+
|
|
180
|
+
## Python API
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from pathlib import Path
|
|
184
|
+
|
|
185
|
+
from parquet_guard import check_file, load_file_contract
|
|
186
|
+
|
|
187
|
+
contract = load_file_contract("file-contract.toml")
|
|
188
|
+
key = Path(".agentsor-file.key").read_bytes()
|
|
189
|
+
result = check_file("output.parquet", contract, fingerprint_key=key)
|
|
190
|
+
print(result.as_dict())
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Applications should protect the key at least as carefully as the local CLI
|
|
194
|
+
does and should not log it.
|
|
195
|
+
|
|
196
|
+
## Deliberate limits
|
|
197
|
+
|
|
198
|
+
- Files larger than 1 TiB and row counts above 1 trillion are outside the v1
|
|
199
|
+
result envelope.
|
|
200
|
+
- Files are read locally by PyArrow; set a realistic `max_bytes` to establish
|
|
201
|
+
a resource boundary before parsing.
|
|
202
|
+
- Duplicate state is atomic and fail-closed but assumes one writer at a time.
|
|
203
|
+
- This release checks completed files; it does not watch producer directories
|
|
204
|
+
or establish that a producer has finished writing.
|
|
205
|
+
- A same-size file that changes during a run is detected by a second keyed
|
|
206
|
+
fingerprint and produces an inconclusive result.
|
|
207
|
+
- Hosted reporting sends only aggregate result metadata; it does not send the
|
|
208
|
+
file, its name or path, column names, values, storage location, or arbitrary
|
|
209
|
+
notes.
|
|
210
|
+
|
|
211
|
+
## Historical Parquet demonstration
|
|
212
|
+
|
|
213
|
+
This repository began as an owned engineering demonstration of a fail-closed,
|
|
214
|
+
idempotent Parquet batch pipeline. That truthful history remains available
|
|
215
|
+
through the compatibility command:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
python examples/generate_sample.py
|
|
219
|
+
parquet-guard --config examples/config.toml
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
It demonstrates validation, deterministic decimal transformation, quarantine,
|
|
223
|
+
atomic output/state, and rerun integrity. It is not client work and is not
|
|
224
|
+
evidence that customer data has been processed. Agentsor File Contracts does
|
|
225
|
+
not silently invoke or quarantine files through that historical command.
|
|
226
|
+
|
|
227
|
+
## Development
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
python -m pip install -e '.[dev]'
|
|
231
|
+
pytest
|
|
232
|
+
ruff check src tests
|
|
233
|
+
python -m build
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The tests cover both formats, config validation, redaction, formal envelope
|
|
237
|
+
validation, project-key isolation, schema stability, bounds, freshness,
|
|
238
|
+
duplicate state, fail-closed state handling, CLI exit behavior, secure init,
|
|
239
|
+
and the historical batch demonstration.
|
|
240
|
+
|
|
241
|
+
For bounded implementation work, see
|
|
242
|
+
[Agentsor Automation Reliability](https://agentsor.ai/automation-reliability).
|
|
243
|
+
Do not send
|
|
244
|
+
credentials, source code, personal data, production records, or confidential
|
|
245
|
+
material by email.
|
|
246
|
+
|
|
247
|
+
License: MIT.
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Agentsor File Contracts
|
|
2
|
+
|
|
3
|
+
Agentsor File Contracts is a free, MIT-licensed command-line tool for checking
|
|
4
|
+
one local CSV or Parquet file against an explicit TOML contract. It checks:
|
|
5
|
+
|
|
6
|
+
- file readability;
|
|
7
|
+
- required columns and Arrow types;
|
|
8
|
+
- unexpected columns;
|
|
9
|
+
- row and byte bounds;
|
|
10
|
+
- optional event-time freshness; and
|
|
11
|
+
- optional duplicate history.
|
|
12
|
+
|
|
13
|
+
`init`, `check`, and `schema` run offline. The separate `report` command checks
|
|
14
|
+
the file locally and sends only the fixed redacted result envelope to the
|
|
15
|
+
single Agentsor collector. The package has no file-upload or telemetry path.
|
|
16
|
+
|
|
17
|
+
## Local quickstart
|
|
18
|
+
|
|
19
|
+
Python 3.11 or newer is required. From this checkout:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python -m venv .venv
|
|
23
|
+
. .venv/bin/activate
|
|
24
|
+
python -m pip install .
|
|
25
|
+
agentsor-file init \
|
|
26
|
+
--format parquet \
|
|
27
|
+
--contract file-contract.toml \
|
|
28
|
+
--fingerprint-key-file .agentsor-file.key
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`init` refuses to replace either target or follow a target symlink. It creates
|
|
32
|
+
a random 32-byte fingerprint key with mode `0600` and never prints the key.
|
|
33
|
+
Edit the generated `[schema]` table to describe the file, then run:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
agentsor-file check YOUR_FILE.parquet \
|
|
37
|
+
--contract file-contract.toml \
|
|
38
|
+
--fingerprint-key-file .agentsor-file.key \
|
|
39
|
+
--state .agentsor-file-state.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The `init`, `check`, and `schema` commands make no network requests. The CLI
|
|
43
|
+
requires the fingerprint key to be an owner-only regular file and refuses
|
|
44
|
+
links or group/world-readable modes. Keep it private and stable within one
|
|
45
|
+
project. Back it up if fingerprint continuity matters.
|
|
46
|
+
|
|
47
|
+
The CLI exits `0` for a passed contract, `1` for a failed or inconclusive
|
|
48
|
+
result, and `2` for a usage, contract, credential, input, transport, or hosted
|
|
49
|
+
receipt error.
|
|
50
|
+
|
|
51
|
+
## Hosted deadline reporting
|
|
52
|
+
|
|
53
|
+
After creating a free monitor at
|
|
54
|
+
[agentsor.ai/file-contracts](https://agentsor.ai/file-contracts), put the
|
|
55
|
+
one-time ingest token in an owner-only credential file without placing it in a
|
|
56
|
+
shell argument:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
mkdir -m 700 -p ~/.config/agentsor
|
|
60
|
+
umask 077
|
|
61
|
+
${EDITOR:-vi} ~/.config/agentsor/file-token
|
|
62
|
+
chmod 600 ~/.config/agentsor/file-token
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then check and submit one redacted result:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
agentsor-file report YOUR_FILE.parquet \
|
|
69
|
+
--contract file-contract.toml \
|
|
70
|
+
--fingerprint-key-file .agentsor-file.key \
|
|
71
|
+
--token-file ~/.config/agentsor/file-token
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`report` has a fixed HTTPS destination, disables inherited proxies and
|
|
75
|
+
redirects, verifies TLS, bounds request/response sizes, validates the complete
|
|
76
|
+
result before network I/O, and never prints the token. It prints a fixed
|
|
77
|
+
acknowledgement containing the run ID, local overall result, duplicate-receipt
|
|
78
|
+
flag, and next hosted deadline.
|
|
79
|
+
|
|
80
|
+
Hosted reporting does not currently accept `--state`; configure
|
|
81
|
+
`reject_duplicates = false` for that command. Use offline `check --state` when
|
|
82
|
+
local duplicate-output detection is required. This avoids mutating duplicate
|
|
83
|
+
state before a network failure can be retried safely.
|
|
84
|
+
|
|
85
|
+
## Contract format
|
|
86
|
+
|
|
87
|
+
```toml
|
|
88
|
+
[contract]
|
|
89
|
+
format = "parquet"
|
|
90
|
+
allow_extra_columns = false
|
|
91
|
+
min_rows = 1
|
|
92
|
+
max_rows = 1000000
|
|
93
|
+
min_bytes = 1
|
|
94
|
+
max_bytes = 104857600
|
|
95
|
+
csv_delimiter = ","
|
|
96
|
+
reject_duplicates = false
|
|
97
|
+
|
|
98
|
+
# Optional; configure both together.
|
|
99
|
+
# event_time_column = "event_time"
|
|
100
|
+
# max_age_seconds = 86400
|
|
101
|
+
|
|
102
|
+
[schema]
|
|
103
|
+
id = "string"
|
|
104
|
+
amount = "double"
|
|
105
|
+
# event_time = "timestamp[ms]"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
`format` may be `csv` or `parquet`, or omitted when one contract intentionally
|
|
109
|
+
supports both. Schema values use PyArrow type aliases. Parquet physical types
|
|
110
|
+
must match exactly. CSV has no physical type metadata, so required CSV columns
|
|
111
|
+
must safely cast to their configured Arrow types.
|
|
112
|
+
|
|
113
|
+
Freshness uses the newest non-null event time. Timestamp columns without a
|
|
114
|
+
timezone are interpreted as UTC. `reject_duplicates = true` requires
|
|
115
|
+
`--state`; without usable state, the result is inconclusive. State contains
|
|
116
|
+
only project-keyed output fingerprints and retains the latest 4,096 unique
|
|
117
|
+
values.
|
|
118
|
+
|
|
119
|
+
## Redacted result envelope
|
|
120
|
+
|
|
121
|
+
`check` writes exactly one JSON object to stdout. The v1 envelope contains a
|
|
122
|
+
canonical run UUID and UTC timestamps, format, bounded row/byte counts, six
|
|
123
|
+
fixed check statuses, fixed reason codes, and three fingerprints. It does not
|
|
124
|
+
contain file paths, file names, column names, raw values, exception messages,
|
|
125
|
+
or arbitrary text.
|
|
126
|
+
|
|
127
|
+
The contract, schema, and output fingerprints are domain-separated
|
|
128
|
+
HMAC-SHA256 values keyed by the supplied project key. They support equality
|
|
129
|
+
and drift checks inside that project without exposing a global raw SHA-256
|
|
130
|
+
that could correlate low-entropy files or schemas across projects.
|
|
131
|
+
|
|
132
|
+
Redaction is not zero knowledge: row/byte counts, timing, outcomes, and
|
|
133
|
+
within-project equality can still reveal metadata. Review that boundary
|
|
134
|
+
before sharing a result.
|
|
135
|
+
|
|
136
|
+
Print the installed formal JSON Schema with:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
agentsor-file schema
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The fixed checks are `readability`, `schema`, `rowBounds`, `byteBounds`,
|
|
143
|
+
`eventFreshness`, and `duplicate`. Required checks use
|
|
144
|
+
`passed|failed|inconclusive`; the two optional checks may also use
|
|
145
|
+
`not_configured`. Overall status is:
|
|
146
|
+
|
|
147
|
+
- `passed` when every check is passed or not configured and reasons are empty;
|
|
148
|
+
- `failed` when at least one check failed; or
|
|
149
|
+
- `inconclusive` when none failed and at least one could not complete.
|
|
150
|
+
|
|
151
|
+
## Python API
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from pathlib import Path
|
|
155
|
+
|
|
156
|
+
from parquet_guard import check_file, load_file_contract
|
|
157
|
+
|
|
158
|
+
contract = load_file_contract("file-contract.toml")
|
|
159
|
+
key = Path(".agentsor-file.key").read_bytes()
|
|
160
|
+
result = check_file("output.parquet", contract, fingerprint_key=key)
|
|
161
|
+
print(result.as_dict())
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Applications should protect the key at least as carefully as the local CLI
|
|
165
|
+
does and should not log it.
|
|
166
|
+
|
|
167
|
+
## Deliberate limits
|
|
168
|
+
|
|
169
|
+
- Files larger than 1 TiB and row counts above 1 trillion are outside the v1
|
|
170
|
+
result envelope.
|
|
171
|
+
- Files are read locally by PyArrow; set a realistic `max_bytes` to establish
|
|
172
|
+
a resource boundary before parsing.
|
|
173
|
+
- Duplicate state is atomic and fail-closed but assumes one writer at a time.
|
|
174
|
+
- This release checks completed files; it does not watch producer directories
|
|
175
|
+
or establish that a producer has finished writing.
|
|
176
|
+
- A same-size file that changes during a run is detected by a second keyed
|
|
177
|
+
fingerprint and produces an inconclusive result.
|
|
178
|
+
- Hosted reporting sends only aggregate result metadata; it does not send the
|
|
179
|
+
file, its name or path, column names, values, storage location, or arbitrary
|
|
180
|
+
notes.
|
|
181
|
+
|
|
182
|
+
## Historical Parquet demonstration
|
|
183
|
+
|
|
184
|
+
This repository began as an owned engineering demonstration of a fail-closed,
|
|
185
|
+
idempotent Parquet batch pipeline. That truthful history remains available
|
|
186
|
+
through the compatibility command:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
python examples/generate_sample.py
|
|
190
|
+
parquet-guard --config examples/config.toml
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
It demonstrates validation, deterministic decimal transformation, quarantine,
|
|
194
|
+
atomic output/state, and rerun integrity. It is not client work and is not
|
|
195
|
+
evidence that customer data has been processed. Agentsor File Contracts does
|
|
196
|
+
not silently invoke or quarantine files through that historical command.
|
|
197
|
+
|
|
198
|
+
## Development
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
python -m pip install -e '.[dev]'
|
|
202
|
+
pytest
|
|
203
|
+
ruff check src tests
|
|
204
|
+
python -m build
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The tests cover both formats, config validation, redaction, formal envelope
|
|
208
|
+
validation, project-key isolation, schema stability, bounds, freshness,
|
|
209
|
+
duplicate state, fail-closed state handling, CLI exit behavior, secure init,
|
|
210
|
+
and the historical batch demonstration.
|
|
211
|
+
|
|
212
|
+
For bounded implementation work, see
|
|
213
|
+
[Agentsor Automation Reliability](https://agentsor.ai/automation-reliability).
|
|
214
|
+
Do not send
|
|
215
|
+
credentials, source code, personal data, production records, or confidential
|
|
216
|
+
material by email.
|
|
217
|
+
|
|
218
|
+
License: MIT.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agentsor-file"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Local CSV and Parquet contracts with redacted hosted receipts"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "Agentsor" }]
|
|
13
|
+
keywords = ["csv", "parquet", "data-contracts", "schema-validation"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"pyarrow>=16,<24",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[project.urls]
|
|
29
|
+
Homepage = "https://agentsor.ai/file-contracts"
|
|
30
|
+
Repository = "https://github.com/linkoinsight/agentsor-file"
|
|
31
|
+
Issues = "https://github.com/linkoinsight/agentsor-file/issues"
|
|
32
|
+
|
|
33
|
+
[project.optional-dependencies]
|
|
34
|
+
dev = [
|
|
35
|
+
"build>=1.2,<2",
|
|
36
|
+
"jsonschema>=4.23,<5",
|
|
37
|
+
"pytest>=8,<10",
|
|
38
|
+
"ruff>=0.12,<0.14",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
agentsor-file = "parquet_guard.file_cli:main"
|
|
43
|
+
parquet-guard = "parquet_guard.cli:main"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.packages.find]
|
|
46
|
+
where = ["src"]
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.package-data]
|
|
49
|
+
parquet_guard = ["py.typed", "schemas/*.json"]
|
|
50
|
+
|
|
51
|
+
[tool.pytest.ini_options]
|
|
52
|
+
addopts = "-q"
|
|
53
|
+
testpaths = ["tests"]
|