@aqaf/cli 0.0.0-stage → 1.1.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.
- package/LICENSE +21 -0
- package/README.md +62 -2
- package/bin/aqaf.js +12 -0
- package/index.js +51 -0
- package/package.json +51 -4
- package/vendor/aqaf/__init__.py +2 -0
- package/vendor/aqaf/__main__.py +3 -0
- package/vendor/aqaf/adapters.py +583 -0
- package/vendor/aqaf/artifacts.py +28 -0
- package/vendor/aqaf/calibration.py +29 -0
- package/vendor/aqaf/catalogue.py +257 -0
- package/vendor/aqaf/cli.py +721 -0
- package/vendor/aqaf/cursor.py +56 -0
- package/vendor/aqaf/data/book_review_knowledge.json +1574 -0
- package/vendor/aqaf/data/catalog.json +562 -0
- package/vendor/aqaf/data/documentation_checks.json +52 -0
- package/vendor/aqaf/data/packs/automation.json +16 -0
- package/vendor/aqaf/data/packs/mobile.json +13 -0
- package/vendor/aqaf/data/packs/systems.json +17 -0
- package/vendor/aqaf/data/packs/web.json +16 -0
- package/vendor/aqaf/data/profiles/ai_pipeline.json +39 -0
- package/vendor/aqaf/data/profiles/android.json +34 -0
- package/vendor/aqaf/data/profiles/api_backend.json +44 -0
- package/vendor/aqaf/data/profiles/browser_extension.json +29 -0
- package/vendor/aqaf/data/profiles/cli_automation.json +34 -0
- package/vendor/aqaf/data/profiles/desktop_utility.json +39 -0
- package/vendor/aqaf/data/profiles/embedded_iot.json +34 -0
- package/vendor/aqaf/data/profiles/google_apps_script.json +34 -0
- package/vendor/aqaf/data/profiles/mcp_agent_server.json +34 -0
- package/vendor/aqaf/data/profiles/multirepo_system.json +29 -0
- package/vendor/aqaf/data/profiles/npm_library.json +39 -0
- package/vendor/aqaf/data/profiles/rust_app.json +34 -0
- package/vendor/aqaf/data/profiles/saas_or_web_app.json +44 -0
- package/vendor/aqaf/data/profiles/scraper_data_pipeline.json +39 -0
- package/vendor/aqaf/data/profiles/swift_app.json +34 -0
- package/vendor/aqaf/data/profiles/tauri_electron.json +34 -0
- package/vendor/aqaf/data/profiles/unknown_or_general_app.json +25 -0
- package/vendor/aqaf/data/profiles/windows_client_server.json +34 -0
- package/vendor/aqaf/data/profiles/wordpress_plugin.json +39 -0
- package/vendor/aqaf/data/review_checks.json +319 -0
- package/vendor/aqaf/data/source_registry.json +814 -0
- package/vendor/aqaf/discovery.py +580 -0
- package/vendor/aqaf/documentation.py +210 -0
- package/vendor/aqaf/evidence.py +132 -0
- package/vendor/aqaf/facets.py +63 -0
- package/vendor/aqaf/ignore.py +109 -0
- package/vendor/aqaf/knowledge.py +110 -0
- package/vendor/aqaf/markup.py +96 -0
- package/vendor/aqaf/matching.py +22 -0
- package/vendor/aqaf/portfolio.py +145 -0
- package/vendor/aqaf/project_commands.py +132 -0
- package/vendor/aqaf/projects.py +157 -0
- package/vendor/aqaf/registry.py +125 -0
- package/vendor/aqaf/review.py +446 -0
- package/vendor/aqaf/scope.py +401 -0
- package/vendor/aqaf/swift_review.py +99 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Bounded data-only continuation identity. Never merge different assessments."""
|
|
2
|
+
import hashlib,json,os,tempfile
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from . import __version__
|
|
5
|
+
|
|
6
|
+
MAX_STATE_BYTES=16384
|
|
7
|
+
MAX_IDENTITY_BYTES=256000000
|
|
8
|
+
MAX_IDENTITY_FILE=1500000
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def runtime_identity():
|
|
12
|
+
root=Path(__file__).parent;digest=hashlib.sha256()
|
|
13
|
+
for path in sorted(root.rglob('*')):
|
|
14
|
+
if path.is_file() and path.suffix in {'.py','.json'} and '__pycache__' not in path.parts:
|
|
15
|
+
digest.update(path.relative_to(root).as_posix().encode()+b'\0'+path.read_bytes())
|
|
16
|
+
return digest.hexdigest()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def identity(scope,options):
|
|
20
|
+
"""Full selected-body hashes under explicit bounds; oversized identity fails closed."""
|
|
21
|
+
digest=hashlib.sha256();total=0
|
|
22
|
+
metadata={'root':str(scope.root),'runtime':runtime_identity(),'version':__version__,'policy':scope.policy,
|
|
23
|
+
'gitignore':scope.respect_gitignore,'ignore_sources':scope.ignore_sources,'config':scope.config,
|
|
24
|
+
'options':{k:v for k,v in options.items() if k!='offset'}}
|
|
25
|
+
digest.update(json.dumps(metadata,sort_keys=True).encode())
|
|
26
|
+
for record in sorted(scope.records,key=lambda r:r['relative']):
|
|
27
|
+
size=record['size'];total+=size
|
|
28
|
+
if size>MAX_IDENTITY_FILE or total>MAX_IDENTITY_BYTES:raise ValueError('Continuation identity exceeds safe full-content bounds; use a smaller component/scope or a fresh independent scan')
|
|
29
|
+
raw=scope.raw(record['path'],MAX_IDENTITY_FILE+1)
|
|
30
|
+
if len(raw)!=size:raise ValueError('Continuation identity input changed or is unreadable')
|
|
31
|
+
digest.update(record['relative'].encode()+b'\0'+hashlib.sha256(raw).digest())
|
|
32
|
+
return digest.hexdigest()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def load(path,expected):
|
|
36
|
+
path=Path(path)
|
|
37
|
+
if path.is_symlink() or not path.is_file() or path.stat().st_size>MAX_STATE_BYTES:raise ValueError('Invalid bounded continuation state')
|
|
38
|
+
try:data=json.loads(path.read_text())
|
|
39
|
+
except (ValueError,OSError,RecursionError) as error:raise ValueError('Invalid continuation JSON') from error
|
|
40
|
+
if not isinstance(data,dict) or data.get('schema_version')!=1 or data.get('identity')!=expected:raise ValueError('Stale continuation: source, root, runtime, scope or budgets changed; start a new scan')
|
|
41
|
+
offset=data.get('next_offset')
|
|
42
|
+
if type(offset) is not int or not 0<=offset<=500000:raise ValueError('Invalid continuation offset')
|
|
43
|
+
return offset
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def write(path,scope,identity_value,next_offset):
|
|
47
|
+
path=Path(path).absolute()
|
|
48
|
+
resolved=path.resolve()
|
|
49
|
+
if resolved==scope.root or scope.root in resolved.parents:raise ValueError('Continuation state must be outside the assessed source')
|
|
50
|
+
if path.exists() or path.is_symlink():raise ValueError('Continuation state already exists; choose a new output file')
|
|
51
|
+
path.parent.mkdir(parents=True,exist_ok=True)
|
|
52
|
+
fd,temporary=tempfile.mkstemp(prefix='.aqaf-cursor-',dir=path.parent)
|
|
53
|
+
try:
|
|
54
|
+
with os.fdopen(fd,'w') as f:json.dump({'schema_version':1,'identity':identity_value,'next_offset':next_offset,'scope':'Independent partial page; previous evidence is not merged or marked complete.'},f,indent=2)
|
|
55
|
+
os.link(temporary,path) # Atomic create without replacing historical state.
|
|
56
|
+
finally:Path(temporary).unlink(missing_ok=True)
|