import Link from "next/link"; import type { ReactNode } from "react"; import type { Metadata } from "next"; import { specMetadata } from "@/lib/page-meta"; import { SiteShell } from "@/components/site-shell"; import { mono, pre, table, td, th } from "../openontology/ui"; import { SENSITIVITY, SOURCES, STEPS } from "./data"; export const metadata: Metadata = specMetadata( "/openerrand", "OpenErrand is one JSON file that describes an errand on a website with no API: the inputs and where each comes from, the rules that fill each field, the human gates a runner must never automate (declarations, identity proofing, codes, letters, captchas), the outcomes, and a hand-off card that never carries a secret." ); const EXCERPT = `"rules": [ { "name": "first name", "id": "^FstName$", "do": { "text": "{{first_name}}" } }, { "name": "net income", "label": "net income|income \\\\(loss\\\\)", "types": ["text", "tel", "number"], "do": { "text": "{{net_income}}" } }, { "name": "declaration", "label": "perjury|i declare|under penalty", "types": ["checkbox"], "do": { "gate": "declaration" } } ], "steps": [ { "id": "declaration", "kind": "declare", "statement": "perjury|i declare|under penalty", "why": "Ticking this box is the representative stating, under penalty of perjury, that what was entered is true." } ]`; const RULES: Array<[string, string]> = [ ["Shows the errand first", "Title, publisher, every gate with its reason, every input with its sensitivity and source. A file whose hash changed is shown again before it runs."], ["Never guesses", "Fields are matched by id first and label second. A required field no rule fills stops the run."], ["Never performs a gate", "Declarations need the person's consent for this run. Identity proofing and letters are theirs, and so are captchas on any sensitive site. Codes come only through a declared relay."], ["One shared secret per run", "A figure from a return is submitted once. A rejection ends the run and lists the other candidates; a person picks the next one."], ["Keeps documents and values in place", "Extraction is local. Values go to the site's fields and the vault; logs hold fields, never values; cards hold steps, never secrets."] ]; export default function OpenErrandPage(): ReactNode { return (

LogicSRC standards surface

OpenErrand

One JSON file that describes an errand a person runs on a website that has no API: registering for a tax account, downloading a transcript, renewing a licence. A person reads it and knows every value it will send and every statement it will ask them to make. An agent runs the same file in a headless browser and stops exactly where a person is needed.

People already automate these sites, with a script nobody else can read or an agent left to guess. The script hides what it sends. The agent ticks a penalty-of-perjury box because the form would not submit without it, and tries a second figure when the first is rejected. OpenErrand writes the errand down: the fields it fills and with what, the values that are secret, the steps that belong to a person, and the point where it stops.

Status: 0.1. A generic runner, logicsrc errand run from{" "} @logicsrc/openerrand, is in progress. The worked example transcribes the rule table of ftb in cli-tools, which registers and activates MyFTB accounts at the California Franchise Tax Board. An excerpt:

{EXCERPT}

Steps and human gates

Five of the seven step kinds are gates: steps only a person can take. A runner hands them over and never performs them, and each carries a why a person reads.

{STEPS.map(([kind, what]) => ( ))}
{kind} {what}

Inputs

Every input has a sensitivity class, which decides where its value may appear.

{SENSITIVITY.map(([name, where]) => ( ))}
class where it may appear
{name} {where}

And an ordered list of sources, tried until one yields a value:

{SOURCES.map(([name, what]) => ( ))}
{name} {what}

What a runner promises

Thirteen rules in the specification; these are the ones that keep a person safe.

{RULES.map(([rule, meaning]) => ( ))}
{rule} {meaning}

Discovery

A publisher lists its errands at /.well-known/openerrand.json, each with the gates it will ask of a person. An errand is verified when it comes from that publisher's origin, and site-endorsed only when the site itself serves the index. This site publishes the worked example at{" "} /.well-known/openerrand.json .

Not

Not a way around a check: a runner may present a normal browser user agent and nothing more, with no fingerprint spoofing, no stealth plugins and no challenge solving. Not for someone else's account. Not an API: when a site has one, use{" "} OpenConnection,{" "} OpenAccess or OpenSaaS. Not a scraper, not a test framework, not a credential store, not legal or tax advice.

Where everything lives

); }