Deterministic Tessie vehicle reads, confirmed controls and health checks through protected dynamic vehicle policy and the existing OneCLI gateway.
73
91%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
"""Vehicle selection and role presentation from the native host policy projection.
Production Runtime loads this schema from `tessie_request` IPC. The host owns
protected VIN/chat policy, verifies source-group identity and enforces every
provider request independently. Agent scratch files grant no authority.
The local file loader remains only for explicitly injected synthetic runtimes.
It is never a fallback when native authority is unavailable. Chat witnessing and
selection here provide additional client-side refusal, not host authorization.
"""
from __future__ import annotations
import json
import os
import stat
from collections.abc import Mapping
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from tessie_core import EXIT_DENIED, VIN_PATTERN, TessieError
ALLOWLIST_PATH = Path("/workspace/state/tessie-ops/allowlist.json")
WITNESS_ENVIRON_PATH = Path("/proc/1/environ")
CHAT_JID_ENV = "NANOCLAW_CHAT_JID"
SUPPORTED_ALLOWLIST_SCHEMA = 1
ROLE_READ = "read"
ROLE_CONTROL = "control"
ROLE_OWNER = "owner"
_ROLE_RANK = {ROLE_READ: 1, ROLE_CONTROL: 2, ROLE_OWNER: 3}
# Denied reasons surfaced to the owner chat; stable strings Tesla2-7 can match.
DENIED_NOT_ALLOWLISTED = "not_allowlisted"
DENIED_UNKNOWN_ALIAS = "unknown_alias"
DENIED_NOT_OWNER_ACCESS = "not_owner_access"
DENIED_INACTIVE = "inactive"
DENIED_NOT_IN_INVENTORY = "not_in_live_inventory"
SELECTOR_REQUIRED = "selector_required"
@dataclass(frozen=True)
class AllowedVehicle:
vin: str
alias: str
shared: bool
@dataclass(frozen=True)
class Allowlist:
vehicles: tuple[AllowedVehicle, ...]
default_vehicle: str | None
owner_chats: frozenset[str]
control_chats: frozenset[str]
read_chats: frozenset[str]
low_battery_percent: int | None
@dataclass(frozen=True)
class LiveVehicle:
vin: str
access_type: str | None
is_active: bool | None
display_name: str | None
car_type: str | None
@dataclass(frozen=True)
class ResolvedVehicle:
vin: str
alias: str
vin_suffix: str
live: LiveVehicle
def _denied(message: str, code: str) -> TessieError:
return TessieError(message, code=code, exit_code=EXIT_DENIED)
def norm_alias(value: str) -> str:
return " ".join(value.split()).casefold()
def vin_suffix(vin: str) -> str:
return vin[-4:]
# --- Allowlist file -----------------------------------------------------------
def _chat_set(raw: Mapping[str, Any], key: str) -> frozenset[str]:
value = raw.get(key, [])
if not isinstance(value, list) or not all(isinstance(i, str) and i for i in value):
raise _denied(
f"allowlist {key!r} must be a list of non-empty chat ids (docs/setup.md)",
"allowlist_invalid",
)
return frozenset(value)
def _parse_vehicle(raw: object, index: int) -> AllowedVehicle:
if not isinstance(raw, dict):
raise _denied(f"allowlist vehicles[{index}] must be an object", "allowlist_invalid")
vin = raw.get("vin")
alias = raw.get("alias")
shared = raw.get("shared", False)
if not isinstance(vin, str) or not VIN_PATTERN.match(vin.upper()):
raise _denied(
f"allowlist vehicles[{index}].vin must be a 17-character VIN", "allowlist_invalid"
)
if not isinstance(alias, str) or not alias.strip():
raise _denied(
f"allowlist vehicles[{index}].alias must be a non-empty string", "allowlist_invalid"
)
if not isinstance(shared, bool):
raise _denied(
f"allowlist vehicles[{index}].shared must be true or false", "allowlist_invalid"
)
return AllowedVehicle(vin=vin.upper(), alias=" ".join(alias.split()), shared=shared)
def parse_allowlist(raw: object) -> Allowlist:
if not isinstance(raw, dict):
raise _denied("allowlist root must be a JSON object", "allowlist_invalid")
schema = raw.get("schema_version")
if schema != SUPPORTED_ALLOWLIST_SCHEMA or isinstance(schema, bool):
raise _denied(
f"allowlist schema_version={schema!r} is not supported (expected "
f"{SUPPORTED_ALLOWLIST_SCHEMA}); update the tessie-ops plugin or fix the file",
"allowlist_schema",
)
entries = raw.get("vehicles")
if not isinstance(entries, list):
raise _denied("allowlist 'vehicles' must be a list", "allowlist_invalid")
vehicles = tuple(_parse_vehicle(item, i) for i, item in enumerate(entries))
seen_vins: set[str] = set()
seen_aliases: set[str] = set()
for vehicle in vehicles:
alias_key = norm_alias(vehicle.alias)
if vehicle.vin in seen_vins or alias_key in seen_aliases:
raise _denied(
f"allowlist lists {vehicle.alias!r} twice (VIN or alias duplicate)",
"allowlist_invalid",
)
seen_vins.add(vehicle.vin)
seen_aliases.add(alias_key)
default = raw.get("default_vehicle")
if default is not None:
if not isinstance(default, str) or norm_alias(default) not in seen_aliases:
raise _denied("allowlist default_vehicle must name a listed alias", "allowlist_invalid")
low_battery: int | None = None
watch = raw.get("watch")
if watch is not None:
if not isinstance(watch, dict):
raise _denied("allowlist 'watch' must be an object", "allowlist_invalid")
value = watch.get("low_battery_percent")
if value is not None:
if isinstance(value, bool) or not isinstance(value, int) or not 1 <= value <= 100:
raise _denied(
"watch.low_battery_percent must be an integer 1..100", "allowlist_invalid"
)
low_battery = value
return Allowlist(
vehicles=vehicles,
default_vehicle=" ".join(default.split()) if isinstance(default, str) else None,
owner_chats=_chat_set(raw, "owner_chats"),
control_chats=_chat_set(raw, "control_chats"),
read_chats=_chat_set(raw, "read_chats"),
low_battery_percent=low_battery,
)
def load_allowlist(path: Path = ALLOWLIST_PATH) -> Allowlist:
try:
info = path.lstat()
except FileNotFoundError as exc:
raise _denied(
f"default deny: no allowlist at {path} — create it as described in docs/setup.md "
"(no vehicle is addressable without one)",
"allowlist_missing",
) from exc
except OSError as exc:
raise _denied(f"cannot stat allowlist {path}: {exc}", "allowlist_unreadable") from exc
if not stat.S_ISREG(info.st_mode):
raise _denied(
f"allowlist {path} must be a regular file, not a link or special file",
"allowlist_invalid",
)
try:
text = path.read_text(encoding="utf-8")
except (OSError, UnicodeDecodeError) as exc:
raise _denied(f"cannot read allowlist {path}: {exc}", "allowlist_unreadable") from exc
try:
raw = json.loads(text)
except json.JSONDecodeError as exc:
raise _denied(
f"allowlist {path} is not valid JSON ({exc}); fix it, nothing is usable until then",
"allowlist_invalid",
) from exc
return parse_allowlist(raw)
# --- Chat authorization -------------------------------------------------------
def witnessed_chat_jid(
*,
environ_path: Path = WITNESS_ENVIRON_PATH,
env: Mapping[str, str] | None = None,
) -> str:
"""The chat id the host gave this container, read from the init process environment."""
process_env = os.environ if env is None else env
try:
raw = environ_path.read_bytes()
except OSError as exc:
raise _denied(
f"cannot witness the chat identity from {environ_path}: {exc}. Controls and "
"location stay denied until the host-provided chat id can be read",
"chat_unwitnessed",
) from exc
witnessed: str | None = None
for item in raw.split(b"\0"):
key, sep, value = item.partition(b"=")
if sep and key == CHAT_JID_ENV.encode("ascii"):
witnessed = value.decode("utf-8", errors="replace")
if not witnessed:
raise _denied(
f"the container init environment carries no {CHAT_JID_ENV}; this chat cannot be "
"authorized",
"chat_unwitnessed",
)
claimed = process_env.get(CHAT_JID_ENV)
if claimed is not None and claimed != witnessed:
raise _denied(
f"{CHAT_JID_ENV} in the command environment disagrees with the host-provided "
"value; refusing (the host value cannot be overridden from a command line)",
"chat_identity_mismatch",
)
return witnessed
def role_for(chat_jid: str, allowlist: Allowlist) -> str | None:
if chat_jid in allowlist.owner_chats:
return ROLE_OWNER
if chat_jid in allowlist.control_chats:
return ROLE_CONTROL
if chat_jid in allowlist.read_chats:
return ROLE_READ
return None
def require_role(role: str | None, minimum: str, purpose: str) -> str:
if role is None:
raise _denied(
f"this chat is not authorized for Tessie ({purpose}): add its id to the allowlist "
"owner_chats, control_chats or read_chats (docs/setup.md)",
"chat_unauthorized",
)
if _ROLE_RANK[role] < _ROLE_RANK[minimum]:
raise _denied(
f"this chat's role {role!r} does not permit {purpose}; it needs {minimum!r}",
"chat_role_insufficient",
)
return role
def authorize(
allowlist: Allowlist,
minimum: str,
purpose: str,
*,
environ_path: Path = WITNESS_ENVIRON_PATH,
env: Mapping[str, str] | None = None,
) -> str:
"""Witness the chat, look up its role, require `minimum`. Returns the role."""
chat = witnessed_chat_jid(environ_path=environ_path, env=env)
return require_role(role_for(chat, allowlist), minimum, purpose)
# --- Live inventory and selection ---------------------------------------------
def parse_inventory(payload: object) -> dict[str, LiveVehicle]:
results = payload.get("results") if isinstance(payload, dict) else None
if not isinstance(results, list):
raise TessieError(
"Tessie /vehicles answered without a 'results' list; report this response shape",
code="malformed_response",
)
inventory: dict[str, LiveVehicle] = {}
for index, item in enumerate(results):
if (
not isinstance(item, dict)
or not isinstance(item.get("vin"), str)
or not VIN_PATTERN.fullmatch(item["vin"].upper())
):
raise TessieError(
f"Tessie /vehicles row {index} lacks a valid VIN; report the response schema",
code="malformed_response",
)
if item["vin"].upper() in inventory:
raise TessieError(
f"Tessie /vehicles row {index} repeats a VIN; report the response schema",
code="malformed_response",
)
last_state = item.get("last_state")
if last_state is not None and not isinstance(last_state, dict):
raise TessieError(
"Tessie /vehicles has an invalid state object; report the schema",
code="malformed_response",
)
state = last_state if isinstance(last_state, dict) else {}
config = state.get("vehicle_config")
if config is not None and not isinstance(config, dict):
raise TessieError(
"Tessie /vehicles has an invalid vehicle config; report the schema",
code="malformed_response",
)
car_type = config.get("car_type") if isinstance(config, dict) else None
access = state.get("access_type", item.get("access_type"))
if (
"access_type" in state
and "access_type" in item
and state["access_type"] != item["access_type"]
):
raise TessieError(
"Tessie /vehicles has conflicting access fields; report the schema",
code="malformed_response",
)
active = item.get("is_active")
display = state.get("display_name")
if (
(access is not None and not isinstance(access, str))
or (active is not None and not isinstance(active, bool))
or (display is not None and not isinstance(display, str))
or (car_type is not None and not isinstance(car_type, str))
):
raise TessieError(
"Tessie /vehicles has malformed row fields; report the schema",
code="malformed_response",
)
vin = item["vin"].upper()
inventory[vin] = LiveVehicle(
vin=vin,
access_type=access if isinstance(access, str) else None,
is_active=active if isinstance(active, bool) else None,
display_name=display if isinstance(display, str) else None,
car_type=car_type if isinstance(car_type, str) else None,
)
return inventory
def denied_reason(entry: AllowedVehicle, live: LiveVehicle | None) -> str | None:
"""None when the listed vehicle is addressable, else the stable denied reason."""
if live is None:
return DENIED_NOT_IN_INVENTORY
if entry.shared:
return None
if live.access_type != "OWNER":
return DENIED_NOT_OWNER_ACCESS
if live.is_active is not True:
return DENIED_INACTIVE
return None
def eligible_entries(
allowlist: Allowlist, inventory: Mapping[str, LiveVehicle]
) -> list[AllowedVehicle]:
return [v for v in allowlist.vehicles if denied_reason(v, inventory.get(v.vin)) is None]
def _find_entry(selector: str, allowlist: Allowlist) -> AllowedVehicle:
wanted = selector.strip()
upper = wanted.upper()
for vehicle in allowlist.vehicles:
if vehicle.vin == upper or norm_alias(vehicle.alias) == norm_alias(wanted):
return vehicle
reason = DENIED_NOT_ALLOWLISTED if VIN_PATTERN.match(upper) else DENIED_UNKNOWN_ALIAS
known = ", ".join(sorted(v.alias for v in allowlist.vehicles)) or "none listed"
raise _denied(
f"vehicle {wanted!r} is not addressable ({reason}); allowlisted aliases: {known}",
reason,
)
def select_vehicle(
selector: str | None,
allowlist: Allowlist,
inventory: Mapping[str, LiveVehicle],
) -> ResolvedVehicle:
"""Resolve an alias/VIN/default to one addressable vehicle, or raise a denial."""
if selector is None:
if allowlist.default_vehicle is not None:
selector = allowlist.default_vehicle
else:
candidates = eligible_entries(allowlist, inventory)
if len(candidates) == 1:
selector = candidates[0].alias
else:
names = ", ".join(sorted(v.alias for v in candidates)) or "none addressable"
raise _denied(
f"choose a vehicle with --vehicle (addressable: {names})", SELECTOR_REQUIRED
)
entry = _find_entry(selector, allowlist)
live = inventory.get(entry.vin)
reason = denied_reason(entry, live)
if reason is not None or live is None:
raise _denied(
f"vehicle {entry.alias!r} is allowlisted but not addressable now ({reason}); "
"no request was sent to it",
reason or DENIED_NOT_IN_INVENTORY,
)
return ResolvedVehicle(
vin=entry.vin, alias=entry.alias, vin_suffix=vin_suffix(entry.vin), live=live
)
def denied_summary(allowlist: Allowlist, inventory: Mapping[str, LiveVehicle]) -> list[dict]:
"""Owner-chat discovery view of everything NOT addressable. No coordinates, no VINs."""
listed = {v.vin: v for v in allowlist.vehicles}
rows: list[dict] = []
for vin, live in inventory.items():
entry = listed.get(vin)
reason = DENIED_NOT_ALLOWLISTED if entry is None else denied_reason(entry, live)
if reason is None:
continue
label = entry.alias if entry is not None else (live.display_name or f"…{vin_suffix(vin)}")
rows.append(
{
"alias_or_suffix": label,
"access_type": live.access_type,
"is_active": live.is_active,
"denied_reason": reason,
}
)
for entry in allowlist.vehicles:
if entry.vin not in inventory:
rows.append(
{
"alias_or_suffix": entry.alias,
"access_type": None,
"is_active": None,
"denied_reason": DENIED_NOT_IN_INVENTORY,
}
)
return rows