feat: queue VedAstro rectification evidence packets
* feat: queue VedAstro rectification evidence packets * fix: make report artifacts portable and normalize d11 * test: use portable runtime smoke temp directory * test: make frontend smoke temp paths portable
This commit is contained in:
@@ -147,3 +147,7 @@ done
|
|||||||
`frontend` local `npm run build` ends during Next.js 16.2.10 compile/static generation, both without configuration and with the CI Supabase placeholders. It leaves no `.next/BUILD_ID` or `.next/prerender-manifest.json`, and no application stack trace. Frontend contracts (`270 passed`), lint, and the selected Python commercial workflow regressions (`128 passed`) remain green.
|
`frontend` local `npm run build` ends during Next.js 16.2.10 compile/static generation, both without configuration and with the CI Supabase placeholders. It leaves no `.next/BUILD_ID` or `.next/prerender-manifest.json`, and no application stack trace. Frontend contracts (`270 passed`), lint, and the selected Python commercial workflow regressions (`128 passed`) remain green.
|
||||||
|
|
||||||
Prevention: do not equate this local host failure with an astrology capability regression. Treat GitHub Actions Node 22 build evidence as the deployment gate before merge. Keep VedAstro `premium_key_missing` and official raw snapshot status explicitly degraded.
|
Prevention: do not equate this local host failure with an astrology capability regression. Treat GitHub Actions Node 22 build evidence as the deployment gate before merge. Keep VedAstro `premium_key_missing` and official raw snapshot status explicitly degraded.
|
||||||
|
|
||||||
|
## ERR-085 | Public production health cannot prove release identity, database migration, or authenticated workflow | active 2026-07-19
|
||||||
|
|
||||||
|
`https://jyotisha.chat` homepage and `/api/health` are reachable and healthy, but those responses do not expose a deployed Git SHA, Supabase migration ledger, evidence-packet TTL policy, or an authorized test-account session. Do not treat HTTP `200` as full release acceptance. Close this only through a deployment-attested SHA plus read-only migration/TTL evidence and an authorized browser acceptance account.
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"benchmark_id": "minute_rectification_holdout_v1",
|
||||||
|
"scope": "public_birth_minute_rectification",
|
||||||
|
"status": "blocked_awaiting_public_aa_cases",
|
||||||
|
"truth_policy": "Only independently published AA birth-minute records and independently sourced dated life events qualify.",
|
||||||
|
"negative_control_policy": "Each case requires blinded false-minute candidates on both sides of the published minute; generated timing-date controls are not substitutes.",
|
||||||
|
"minimum_gate": {
|
||||||
|
"public_aa_cases": 20,
|
||||||
|
"events_per_case": 3,
|
||||||
|
"negative_minutes_per_case": 4
|
||||||
|
},
|
||||||
|
"cases": [],
|
||||||
|
"boundary": "This empty protocol is not evidence of minute-level accuracy. It blocks any verified-minute claim until independent public cases and negative controls are frozen."
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import secrets
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
import tempfile
|
||||||
import uuid
|
import uuid
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
@@ -1312,7 +1313,10 @@ MAX_IMPORT_FILE_BYTES = 1536 * 1024
|
|||||||
MAX_IMPORT_TEXT_CHARS = 500_000
|
MAX_IMPORT_TEXT_CHARS = 500_000
|
||||||
MAX_REPORT_HTML_CHARS = 1_200_000
|
MAX_REPORT_HTML_CHARS = 1_200_000
|
||||||
MAX_REPORT_BASE64_BYTES = 8 * 1024 * 1024
|
MAX_REPORT_BASE64_BYTES = 8 * 1024 * 1024
|
||||||
REPORT_ARTIFACT_DIR = os.path.join('/private/tmp', 'jyotish-reports')
|
REPORT_ARTIFACT_DIR = os.environ.get(
|
||||||
|
'JYOTISH_REPORT_ARTIFACT_DIR',
|
||||||
|
os.path.join(tempfile.gettempdir(), 'jyotish-reports'),
|
||||||
|
)
|
||||||
|
|
||||||
API_COMMAND_MAP = {
|
API_COMMAND_MAP = {
|
||||||
'chart': '/api/chart',
|
'chart': '/api/chart',
|
||||||
@@ -6986,7 +6990,11 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
|
|||||||
'lat': lat,
|
'lat': lat,
|
||||||
'lon': lon,
|
'lon': lon,
|
||||||
'tz': tz,
|
'tz': tz,
|
||||||
})
|
},
|
||||||
|
enqueue_vedastro_gateway=True,
|
||||||
|
vedastro_question='High-rigor birth-time rectification evidence packet',
|
||||||
|
vedastro_reference_date=datetime.now().strftime('%Y-%m-%d'),
|
||||||
|
)
|
||||||
result['can_apply'] = False
|
result['can_apply'] = False
|
||||||
result.setdefault('reasons', []).append('three_engine_parity_not_passed')
|
result.setdefault('reasons', []).append('three_engine_parity_not_passed')
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -4923,6 +4923,17 @@ def cmd_full_reading(args):
|
|||||||
)
|
)
|
||||||
except Exception as d11_error:
|
except Exception as d11_error:
|
||||||
varga_result["D11_Rudramsa"] = {"error": str(d11_error)}
|
varga_result["D11_Rudramsa"] = {"error": str(d11_error)}
|
||||||
|
d11 = varga_result.get("D11_Rudramsa")
|
||||||
|
if isinstance(d11, dict) and isinstance(d11.get("Ascendant"), dict):
|
||||||
|
asc_sign = d11["Ascendant"].get("sign_idx")
|
||||||
|
if isinstance(asc_sign, int):
|
||||||
|
d11["planets"] = {
|
||||||
|
name: {**data, "house": ((int(data["sign_idx"]) - asc_sign) % 12) + 1}
|
||||||
|
for name, data in d11.items()
|
||||||
|
if name not in {"_meta", "Ascendant", "planets"}
|
||||||
|
and isinstance(data, dict)
|
||||||
|
and isinstance(data.get("sign_idx"), int)
|
||||||
|
}
|
||||||
report['modules']['varga_full'] = varga_result
|
report['modules']['varga_full'] = varga_result
|
||||||
|
|
||||||
# v6.1.7: Re-run Yoga with D9/D60 context after varga-full is available.
|
# v6.1.7: Re-run Yoga with D9/D60 context after varga-full is available.
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Validate the public, minute-specific rectification holdout gate."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
DEFAULT_MANIFEST = ROOT / "references" / "real_case_calibration" / "minute_rectification_holdout_v1.json"
|
||||||
|
|
||||||
|
|
||||||
|
def validate(manifest_path: Path = DEFAULT_MANIFEST) -> dict[str, Any]:
|
||||||
|
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||||
|
gate = manifest.get("minimum_gate") if isinstance(manifest.get("minimum_gate"), dict) else {}
|
||||||
|
cases = manifest.get("cases") if isinstance(manifest.get("cases"), list) else []
|
||||||
|
valid_cases = 0
|
||||||
|
invalid: list[str] = []
|
||||||
|
for case in cases:
|
||||||
|
if not isinstance(case, dict):
|
||||||
|
invalid.append("non_object_case")
|
||||||
|
continue
|
||||||
|
birth = case.get("birth_source") if isinstance(case.get("birth_source"), dict) else {}
|
||||||
|
events = case.get("events") if isinstance(case.get("events"), list) else []
|
||||||
|
negatives = case.get("negative_minutes") if isinstance(case.get("negative_minutes"), list) else []
|
||||||
|
required = birth.get("time_accuracy_rating") == "AA" and bool(birth.get("url"))
|
||||||
|
required = required and len(events) >= int(gate.get("events_per_case", 3))
|
||||||
|
required = required and len(negatives) >= int(gate.get("negative_minutes_per_case", 4))
|
||||||
|
if required:
|
||||||
|
valid_cases += 1
|
||||||
|
else:
|
||||||
|
invalid.append(str(case.get("case_id") or "unnamed_case"))
|
||||||
|
needed = int(gate.get("public_aa_cases", 20))
|
||||||
|
status = "ready_for_blind_replay" if valid_cases >= needed else "blocked_awaiting_public_aa_cases"
|
||||||
|
return {
|
||||||
|
"scope": "minute_rectification_holdout_validation",
|
||||||
|
"benchmark_id": manifest.get("benchmark_id"),
|
||||||
|
"status": status,
|
||||||
|
"valid_public_aa_cases": valid_cases,
|
||||||
|
"minimum_public_aa_cases": needed,
|
||||||
|
"invalid_cases": invalid,
|
||||||
|
"verified_minute_claim_allowed": False,
|
||||||
|
"boundary": manifest.get("boundary"),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(json.dumps(validate(), ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
@@ -51,7 +51,44 @@ def _jyotishganit_d1(case: dict[str, Any]) -> dict[str, str]:
|
|||||||
sys.path.remove(str(JYOTISHGANIT_ROOT))
|
sys.path.remove(str(JYOTISHGANIT_ROOT))
|
||||||
|
|
||||||
|
|
||||||
def build_packet(case: dict[str, Any]) -> dict[str, Any]:
|
def _gateway_job_receipt(job: dict[str, Any]) -> dict[str, Any]:
|
||||||
|
"""Return only pollable, non-sensitive VedAstro job state for a packet."""
|
||||||
|
archive = job.get("raw_response_archive")
|
||||||
|
archive = archive if isinstance(archive, dict) else {}
|
||||||
|
return {
|
||||||
|
"scope": "vedastro_gateway_job_receipt",
|
||||||
|
"status": str(job.get("status") or "blocked"),
|
||||||
|
"job_id": str(job.get("job_id") or ""),
|
||||||
|
"poll_path": str(job.get("poll_path") or ""),
|
||||||
|
"raw_response_archive": {
|
||||||
|
"status": str(archive.get("status") or "unknown"),
|
||||||
|
"official_raw_response_available": bool(archive.get("official_raw_response_available")),
|
||||||
|
},
|
||||||
|
"boundary": "VedAstro raw response remains server-side; this receipt never returns request data or raw evidence.",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _enqueue_vedastro_gateway_job(
|
||||||
|
case: dict[str, Any], *, question: str = "", reference_date: str = ""
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
from scripts.vedastro_gateway import enqueue_gateway_job
|
||||||
|
|
||||||
|
job = enqueue_gateway_job(
|
||||||
|
case,
|
||||||
|
question=question,
|
||||||
|
themes=["rectification"],
|
||||||
|
reference_date=reference_date,
|
||||||
|
)
|
||||||
|
return _gateway_job_receipt(job)
|
||||||
|
|
||||||
|
|
||||||
|
def build_packet(
|
||||||
|
case: dict[str, Any],
|
||||||
|
*,
|
||||||
|
enqueue_vedastro_gateway: bool = False,
|
||||||
|
vedastro_question: str = "",
|
||||||
|
vedastro_reference_date: str = "",
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Compare local/PyJHora/jyotishganit D1 without persisting private input."""
|
"""Compare local/PyJHora/jyotishganit D1 without persisting private input."""
|
||||||
required = {"year", "month", "day", "hour", "minute", "lat", "lon", "tz"}
|
required = {"year", "month", "day", "hour", "minute", "lat", "lon", "tz"}
|
||||||
if not required <= set(case):
|
if not required <= set(case):
|
||||||
@@ -66,6 +103,21 @@ def build_packet(case: dict[str, Any]) -> dict[str, Any]:
|
|||||||
outputs[name] = {}
|
outputs[name] = {}
|
||||||
engine_status[name] = f"blocked:{exc.__class__.__name__}"
|
engine_status[name] = f"blocked:{exc.__class__.__name__}"
|
||||||
rows = [{"planet": planet, "values": {name: data.get(planet) for name, data in outputs.items()}, "status": "match" if len({data.get(planet) for data in outputs.values()}) == 1 else "mismatch"} for planet in PLANETS]
|
rows = [{"planet": planet, "values": {name: data.get(planet) for name, data in outputs.items()}, "status": "match" if len({data.get(planet) for data in outputs.values()}) == 1 else "mismatch"} for planet in PLANETS]
|
||||||
|
vedastro = {"status": "requires_gateway_raw_archive"}
|
||||||
|
if enqueue_vedastro_gateway:
|
||||||
|
try:
|
||||||
|
vedastro = _enqueue_vedastro_gateway_job(
|
||||||
|
case,
|
||||||
|
question=vedastro_question,
|
||||||
|
reference_date=vedastro_reference_date,
|
||||||
|
)
|
||||||
|
except Exception as exc:
|
||||||
|
vedastro = {
|
||||||
|
"scope": "vedastro_gateway_job_receipt",
|
||||||
|
"status": "blocked",
|
||||||
|
"reason": f"gateway_enqueue_failed:{exc.__class__.__name__}",
|
||||||
|
"boundary": "VedAstro raw response remains server-side; no raw evidence was returned.",
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
"scope": "request_level_three_engine_d1_parity",
|
"scope": "request_level_three_engine_d1_parity",
|
||||||
"case_hash": case_hash(case),
|
"case_hash": case_hash(case),
|
||||||
@@ -73,7 +125,7 @@ def build_packet(case: dict[str, Any]) -> dict[str, Any]:
|
|||||||
"match_count": sum(row["status"] == "match" for row in rows),
|
"match_count": sum(row["status"] == "match" for row in rows),
|
||||||
"mismatch_count": sum(row["status"] == "mismatch" for row in rows),
|
"mismatch_count": sum(row["status"] == "mismatch" for row in rows),
|
||||||
"rows": rows,
|
"rows": rows,
|
||||||
"vedastro": {"status": "requires_gateway_raw_archive"},
|
"vedastro": vedastro,
|
||||||
"can_confirm": False,
|
"can_confirm": False,
|
||||||
"boundary": "D1 parity alone never confirms a rectified minute; VedAstro raw and domain-level parity remain required.",
|
"boundary": "D1 parity alone never confirms a rectified minute; VedAstro raw and domain-level parity remain required.",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import signal
|
|||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -18,7 +19,7 @@ from typing import Any
|
|||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
APP = ROOT / "jyotish-app"
|
APP = ROOT / "jyotish-app"
|
||||||
API_SERVER = ROOT / "scripts" / "jyotish_api_server.py"
|
API_SERVER = ROOT / "scripts" / "jyotish_api_server.py"
|
||||||
TMP = Path(os.environ.get("TMPDIR", "/private/tmp"))
|
TMP = Path(os.environ.get("TMPDIR") or tempfile.gettempdir())
|
||||||
SYSTEM_CHROME = Path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
|
SYSTEM_CHROME = Path("/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")
|
||||||
OFFLINE_CONSOLE_ERROR_MARKERS = [
|
OFFLINE_CONSOLE_ERROR_MARKERS = [
|
||||||
"ERR_CONNECTION_REFUSED",
|
"ERR_CONNECTION_REFUSED",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any
|
from typing import Any
|
||||||
@@ -16,7 +17,7 @@ from typing import Any
|
|||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
APP = ROOT / "jyotish-app"
|
APP = ROOT / "jyotish-app"
|
||||||
API_SERVER = ROOT / "scripts" / "jyotish_api_server.py"
|
API_SERVER = ROOT / "scripts" / "jyotish_api_server.py"
|
||||||
TMP = Path(os.environ.get("TMPDIR", "/private/tmp"))
|
TMP = Path(os.environ.get("TMPDIR") or tempfile.gettempdir())
|
||||||
|
|
||||||
|
|
||||||
def run(cmd: list[str], *, cwd: Path = ROOT, timeout: int = 12, check: bool = True) -> subprocess.CompletedProcess[str]:
|
def run(cmd: list[str], *, cwd: Path = ROOT, timeout: int = 12, check: bool = True) -> subprocess.CompletedProcess[str]:
|
||||||
|
|||||||
@@ -404,3 +404,40 @@ def test_gochara_conflict_downgrades_without_verified_timing_claim_red() -> None
|
|||||||
assert top["confidence_cap"] == "low"
|
assert top["confidence_cap"] == "low"
|
||||||
assert "gochara_transit" in top["downgrade_reasons"]
|
assert "gochara_transit" in top["downgrade_reasons"]
|
||||||
assert scored["timing_claim_status"] == "exploratory_unvalidated"
|
assert scored["timing_claim_status"] == "exploratory_unvalidated"
|
||||||
|
|
||||||
|
|
||||||
|
def test_high_rigor_event_rectification_queues_vedastro_packet(monkeypatch) -> None:
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"scripts.rectification_three_engine_packet._enqueue_vedastro_gateway_job",
|
||||||
|
lambda *_args, **_kwargs: {
|
||||||
|
"scope": "vedastro_gateway_job_receipt",
|
||||||
|
"status": "queued",
|
||||||
|
"job_id": "vgw_rectification",
|
||||||
|
"poll_path": "/api/vedastro_gateway/jobs/vgw_rectification",
|
||||||
|
"raw_response_archive": {
|
||||||
|
"status": "pending",
|
||||||
|
"official_raw_response_available": False,
|
||||||
|
},
|
||||||
|
"boundary": "VedAstro raw response remains server-side; this receipt never returns request data or raw evidence.",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
result = _handler()._compute_active_rectification_events(
|
||||||
|
{
|
||||||
|
"birth_date": "1993-04-17",
|
||||||
|
"start_time": "14:29",
|
||||||
|
"end_time": "14:31",
|
||||||
|
"lat": 36.683333,
|
||||||
|
"lon": 114.35,
|
||||||
|
"tz": 8,
|
||||||
|
"high_rigor": True,
|
||||||
|
"events": [
|
||||||
|
{"id": "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5", "domain": "education", "date": "2011-09", "precision": "month"},
|
||||||
|
{"id": "0790866c-ad5e-4a45-b2b4-a5c73f6be6ea", "domain": "career", "date": "2019-07-01", "precision": "day"},
|
||||||
|
{"id": "0ef52e51-ab5f-453b-81e5-adb44a929224", "domain": "relationship", "date": "2021", "precision": "year"},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
receipt = result["three_engine_packet"]["vedastro"]
|
||||||
|
assert receipt["status"] == "queued"
|
||||||
|
assert receipt["job_id"] == "vgw_rectification"
|
||||||
|
assert "1993" not in str(receipt)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
@@ -19,7 +20,7 @@ import pytest
|
|||||||
ROOT = Path(__file__).resolve().parents[1]
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
APP = ROOT / "jyotish-app"
|
APP = ROOT / "jyotish-app"
|
||||||
API_SERVER = ROOT / "scripts" / "jyotish_api_server.py"
|
API_SERVER = ROOT / "scripts" / "jyotish_api_server.py"
|
||||||
TMP = Path(os.environ.get("TMPDIR", "/private/tmp"))
|
TMP = Path(os.environ.get("TMPDIR") or tempfile.gettempdir())
|
||||||
|
|
||||||
|
|
||||||
def read(relative: str) -> str:
|
def read(relative: str) -> str:
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
from scripts.minute_rectification_holdout_validator import validate
|
||||||
|
|
||||||
|
|
||||||
|
def test_empty_public_minute_protocol_blocks_verified_claims() -> None:
|
||||||
|
report = validate()
|
||||||
|
assert report["status"] == "blocked_awaiting_public_aa_cases"
|
||||||
|
assert report["verified_minute_claim_allowed"] is False
|
||||||
|
assert report["valid_public_aa_cases"] == 0
|
||||||
@@ -13,3 +13,39 @@ def test_packet_is_private_and_never_confirms(monkeypatch) -> None:
|
|||||||
assert "year" not in str(packet)
|
assert "year" not in str(packet)
|
||||||
assert packet["can_confirm"] is False
|
assert packet["can_confirm"] is False
|
||||||
assert packet["vedastro"]["status"] == "requires_gateway_raw_archive"
|
assert packet["vedastro"]["status"] == "requires_gateway_raw_archive"
|
||||||
|
|
||||||
|
|
||||||
|
def test_high_rigor_packet_queues_safe_vedastro_receipt_without_raw(monkeypatch) -> None:
|
||||||
|
monkeypatch.setattr("scripts.rectification_three_engine_packet._local_d1", lambda _: {"Sun": "Aries"})
|
||||||
|
monkeypatch.setattr("scripts.rectification_three_engine_packet._pyjhora_d1", lambda _: {"Sun": "Aries"})
|
||||||
|
monkeypatch.setattr("scripts.rectification_three_engine_packet._jyotishganit_d1", lambda _: {"Sun": "Aries"})
|
||||||
|
monkeypatch.setattr(
|
||||||
|
"scripts.vedastro_gateway.enqueue_gateway_job",
|
||||||
|
lambda *_args, **_kwargs: {
|
||||||
|
"job_id": "vgw_safe_receipt",
|
||||||
|
"status": "queued",
|
||||||
|
"poll_path": "/api/vedastro_gateway/jobs/vgw_safe_receipt",
|
||||||
|
"request": CASE,
|
||||||
|
"result": {"official_raw_response": {"private": "never expose"}},
|
||||||
|
"raw_response_archive": {
|
||||||
|
"status": "pending",
|
||||||
|
"official_raw_response_available": False,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
packet = build_packet(CASE, enqueue_vedastro_gateway=True)
|
||||||
|
|
||||||
|
assert packet["vedastro"] == {
|
||||||
|
"scope": "vedastro_gateway_job_receipt",
|
||||||
|
"status": "queued",
|
||||||
|
"job_id": "vgw_safe_receipt",
|
||||||
|
"poll_path": "/api/vedastro_gateway/jobs/vgw_safe_receipt",
|
||||||
|
"raw_response_archive": {
|
||||||
|
"status": "pending",
|
||||||
|
"official_raw_response_available": False,
|
||||||
|
},
|
||||||
|
"boundary": "VedAstro raw response remains server-side; this receipt never returns request data or raw evidence.",
|
||||||
|
}
|
||||||
|
assert "year" not in str(packet)
|
||||||
|
assert "private" not in str(packet)
|
||||||
|
|||||||
Reference in New Issue
Block a user