{"agent_delegation":{"addressing":{"alternatives":["Existing app-owned hostnames","Operator-enabled managed hostnames","Trusted public-IP TLS certificates when the registration adapter supports them"],"boundary":"Invitation branding and callback email are independent of gateway addressing. Ordinary setup does not grant managed DNS, managed email, or white-label entitlements.","default":"An app may turn a public instance IP into an sslip.io hostname and automate HTTPS without changing its owner's DNS. This uses external DNS and remains optional.","owned_zone_example":"Optionally delegate deploy.example.com once using NS records to app-operated authoritative nameservers, with A/AAAA records for the nameservers. The app can publish authorized names automatically without per-instance DNS logins. A wildcard A record to one IP only covers a shared ingress. This is optional app infrastructure, independent of branding and email.","requirements":["Use an authorized public IP and a unique IP-backed hostname; verify DNS resolves to that host.","Configure ingress for the exact hostname and container, and obtain trusted HTTPS; sslip.io supplies DNS, not certificates.","HTTP-01 ACME needs public TCP 80 at its challenge handler; HTTPS service needs TCP 443. Other challenge methods have their own requirements.","Verify DNS, TLS, registration/conformance, invitation redemption, and direct instance access. DNS does not grant host or private-network access."]},"contract":["The application retains its Owlshare service credential; never give it to a delegated setup agent or user-agent.","An authorized agent asks the application to create a bounded authorization offer. The application creates an ordinary Owlshare invitation carrying its authorization_id.","The recipient redeems the invitation and enrolls at the application. The application checks the signed ticket against the saved offer and issues its own revocable credential.","Delegated actions, resources, quotas, expiry, and further-sharing authority must fit within the issuing agent's authority. Check the ancestor chain on use and enrollment.","Instance setup and instance access are separate grants. Return the instance's direct HTTPS endpoint in the user-agent connection manifest."],"guide_url":"https://owlshare.io/agent-delegation","roles":["app setup agent","instance setup agent","instance user-agent"]},"agent_instructions":["Create a registration session only when your owner has asked you to connect a web service they run.","Use the supplied deployment target and automatic IP hostname default when no hostname is specified. Do not require a human DNS-provider choice. Ask for missing deployment authority or target information; changes to owner-controlled DNS and optional paid capabilities need separate authorization.","Deploy the required service manifest, ticket endpoint, and authenticated MCP endpoint at the registered HTTPS origin.","Implement the authenticated MCP conformance path described by the registration response; REST-only services do not pass Layer 1 registration.","Keep the registration token and final service credential private.","Call the session verification endpoint and require status active before continuing. Active means Owlshare registration and conformance passed; it does not mean the application is ready for users.","Run the post_activation_conformance checks against an ordinary disposable enrollment. Report the application ready only after its useful authorized operation, denial, replay, revocation, restart, and cleanup checks pass."],"invitation_branding":{"boundary":"Custom invitation URLs do not change signed-ticket issuer, gateway addressing, direct instance access, or callback email. Keep the app credential private; expose configuration only through the app's authorized administrator flow.","custom_url":"An operator must authorize the app and exact HTTPS prefix first. The app's existing website can proxy only that share path to Owlshare without changing DNS providers.","default":"Owlshare invitation URLs work immediately after registration.","discovery":"GET /v1/services/{id}/profile with the service credential reports available branding configuration. Only the authorized parent app may configure and verify its approved URL; delegated instance credentials cannot."},"invitation_contract":{"authentication":"Bearer \u003cservice_token\u003e","body":{"authorization_id":"optional application-owned delegation offer ID; copied into the signed ticket, not interpreted by Owlshare","expires_minutes":"optional integer 1..10080; defaults to 30; invitation redemption deadline is separate from service access and funding deadlines","label":"optional human-readable context, at most 200 characters","recipient_agent_id":"optional existing Owlshare identity ID","resource_id":"required safe identifier, 1..100 characters","resource_name":"required display name, 2..120 characters","scopes":"optional array of at most 20 safe tokens, each at most 80 characters"},"content_type":"application/json","method":"POST","reconciliation":"GET invitation_collection is the authoritative ready/used/revoked/expired state. Layer 1 may reconcile its local journal after enrollment because no consumption callback is guaranteed.","response":{"identity_offer":{"code":"response.invitation.code","private_offer_id":"response.private_offer_id","public_redemption":"false"},"public_invitation":{"code":"response.invitation.code","expires_at":"response.invitation.expires_at","url":"response.url"},"status":201},"strict_body":"Unknown JSON fields are rejected. Use these exact field names.","when":"After activation, use the returned invitation_endpoint and service_token."},"issue_queue":{"authentication":"service bearer credential","categories":["bug","integration","missing_capability","efficiency","clarification"],"collection":"/v1/services/{service_id}/tickets","methods":["GET","POST"],"operator_queue":"/admin/tickets","privacy":"Only the reporting service and Owlshare operator can read the issue. Omit secrets, credentials and capability URLs."},"manifest_path":"/.well-known/owlshare-service","manifest_schema_url":"https://owlshare.io/schemas/owlshare-service-v1","next":"The registration response contains the challenge, proof format, exact endpoints, and verification request.","ongoing_health":{"authentication":"service bearer credential","check":"POST /v1/services/{service_id}/health/check","freshness_seconds":900,"report":"GET /v1/services/{service_id}/health","scope":"Live origin/identity, signed conformance, replay and enrollment isolation, MCP. Also run app acceptance tests; registration is not perpetual readiness."},"origin_migration":{"contract":["Serve the new origin with the same Ed25519 service identity; a new key is rejected.","Sign the returned proof_message and exchange Owlshare's conformance ticket only for the short-lived MCP self-test credential at the new origin.","Call verify only after the new origin is ready. Owlshare then updates generated enrollment links without replacing the service ID, credential, invitations, or grants.","Keep the old origin serving during the recommended overlap; rollback is available for one hour after activation.","Finalize only after application-generated URLs and existing credentials have been tested on the new origin."],"create":{"authentication":"Bearer \u003cservice_token\u003e","body":{"base_url":"new public HTTPS origin"},"method":"POST","url_template":"https://owlshare.io/v1/services/{service_id}/origin-migrations"}},"owner_decisions":{"optional":[{"choices":["poll","webhook","email"],"default":"poll","email_follow_up":["Which SMTP relay should send the opaque wake messages?","Which From address is authorized for that relay?","How will the deployment receive the relay credential without placing it in source control?"],"id":"event_delivery","prompt":"Should this service support polling only, webhook wakes, or email wakes?","rules":["Email is optional and is not used to prove service ownership.","Do not request SMTP choices when email delivery is not selected.","Require TLS and keep mail credentials in deployment secrets."],"when":"The Layer 1 service can emit asynchronous events or alerts."}],"required":[{"choices":[{"id":"owned_hostname","use":"Production or durable service identity; use a hostname the owner controls."},{"id":"automatic_ip_hostname","use":"When an authorized deployment has a public IPv4 address and no chosen hostname, generate a unique IP-backed sslip.io hostname and automate valid HTTPS. No DNS-provider account or human DNS change is needed. Report the external DNS dependency."}],"default":"automatic_ip_hostname_when_public_ipv4_available","id":"public_https_origin","prompt":"Resolve the service's public HTTPS origin from its deployment target.","rules":["Use a supplied HTTPS origin when present; otherwise use the automatic IP hostname default for an authorized public deployment.","Ask only when the deployment target or required infrastructure authority is missing, not to choose a DNS provider.","Do not claim a hostname on someone else's owned domain or alter their DNS without authorization.","A literal IP address is not currently accepted by this registration adapter.","Record that an IP-backed hostname depends on its external DNS service and the instance's IP. An owned hostname is an optional later migration."]}]},"post_activation_conformance":{"boundary":"Owlshare can verify its own invitation lifecycle generically. The Layer 1 service must supply and run its application-specific useful-request and authorization checks.","cleanup":"Revoke unused Layer 0 invitations through the service-authenticated invitation endpoint and delete/revoke all disposable Layer 1 state.","first_owner_bootstrap":["Define one narrow service-level resource and scope combination that the Layer 1 application recognizes for creating its first owner.","Using the newly returned service credential, create a short-lived invitation with exactly that application-defined resource and scopes.","Redeem and enroll a disposable recipient, then make one useful authorized application request.","Do not give the Layer 0 service credential to the recipient agent; only the deployment/operator agent retains it."],"mcp":["Expose the application's agent tools through authenticated MCP Streamable HTTP at mcp_url; REST may remain available but is not a substitute.","Support MCP protocol 2025-11-25 as the compatibility baseline and enforce the same permissions as the corresponding application API.","Include an owlshare_self_test tool. A conformance credential may call only that tool, expires within five minutes, and never authorizes application data.","After normal enrollment, prove initialize, tools/list, one useful application tool call, denial outside the grant, and revocation through MCP."],"purpose":"Prove the application's real authorization path after Layer 0 origin verification. Registration alone is not end-to-end conformance.","required_negative_checks":["invitation reuse fails","ticket replay fails","unsupported resource or scope fails","unauthorized application action fails","revoked application credential fails after restart"]},"protocol_version":"1","registration":{"body_schema":{"base_url":"Public HTTPS origin controlled by the service","deployment_token":"Optional one-time token from a registered parent application","name":"Public service name, 2..100 characters"},"content_type":"application/json","method":"POST","url":"https://owlshare.io/v1/service-registrations"},"schema":"https://owlshare.io/schemas/service-connect-v1","sdk":{"agent_rules":["Discuss unresolved hosting, provider, hostname and notification choices with the owner before configuring them. Use already authorized choices without asking again.","Hosting, email accounts, paid services and secret access are supplied by the owner or their authorized infrastructure; this guide does not provision them.","Keep credentials in private deployment secrets, never ticket text, source, logs or setup responses.","Polling remains available. Email and webhooks require recipient consent and destination confirmation.","Track configured, tested and receiver-confirmed separately. Owlshare registration active proves registration conformance, not complete application or notification readiness.","Publish application-specific configuration and acceptance tests in your application's setup guide; keep them outside the reusable SDK and strict Owlshare service manifest."],"callback_contract_url":"https://owlshare.io/v1/sdk/v0.2.1/callbacks","capabilities_url":"https://owlshare.io/v1/sdk/v0.2.1/capabilities","contains":["language-independent API contracts, JSON schemas and acceptance checklist","runnable Go reference service","registration, enrollment, grants and isolated MCP conformance","optional integration clients, notifications and support tickets"],"contract_url":"https://owlshare.io/v1/sdk/v0.2.1/contracts","go_required":false,"guide_url":"https://owlshare.io/v1/sdk/v0.2.1","integration":["Fetch this guide and the pinned source archive from Owlshare; no Forgejo credential is needed.","Verify source_sha256 before extracting the archive into your application's dependency source directory. Keep the version and checksum with the application's source.","The archive contains a Go module; use a local go.mod replace pointing at that extracted directory, or vendor the pinned module. Do not resolve a newer version implicitly.","Implement application routes, transactional persistence and credential liveness around the libraries. Persist a ticket update and its opaque callback job in the same transaction, then deliver outside storage locks.","The Owlshare API and protocol define required behavior in any language. The Go reference service implements registration, enrollment and MCP conformance; adapt its host authorization and durable storage to your application. Optional modules require their own configured and tested application routes.","Run go test -race ./... and go vet ./... in the extracted SDK and your application; test actual recipient delivery separately."],"language":"any","module":"forgejo.owlbox.ai/ben/owl-agent-sdk","owner_choices":[{"id":"hosting","questions":["Which authorized host or hosting provider will run this service?","Where should durable state and backups live?"],"required":true,"test":"restart preserves grants, tickets and pending delivery jobs"},{"id":"origin","parameters":["application public HTTPS origin","TLS certificate and ingress routing"],"questions":["Use an existing owned HTTPS hostname, or an automatic IP-backed hostname for the authorized host?"],"required":true,"test":"trusted HTTPS and correct same-origin manifest/enrollment/API/MCP endpoints"},{"choices":["poll","webhook","email"],"default":"poll","id":"notifications","required":false,"test":"destination confirmation plus delivered wake, authenticated retrieval and application acknowledgement where supported"},{"id":"email","parameters":["SMTP_ADDR","SMTP_FROM","SMTP_USERNAME (optional)","SMTP_PASSWORD (optional)","SMTP_NETWORK (tcp default; tcp4/tcp6 when required by relay policy)"],"questions":["Which relay and authorized sender should be used?","How will the host receive any required secret securely?"],"test":"STARTTLS, authorized sender, real recipient confirmation and delivery; SMTP acceptance alone is insufficient","when":"email selected"},{"id":"webhook","parameters":["recipient-owned public HTTPS callback URL","privately generated webhook secret","opaque wake payload"],"test":"confirmation, HMAC signature/timestamp verification and wake ID deduplication","when":"webhook selected"},{"id":"authorization","parameters":["registered Owlshare service identity","application-owned grant storage and resource permissions"],"required":true,"test":"wrong-service ticket rejection, single-use enrollment, cross-owner isolation, revocation and delegation boundaries"}],"protocol":"owlshare-sdk-setup-v1","readme_url":"https://owlshare.io/v1/sdk/v0.2.1/readme","reference_url":"https://owlshare.io/v1/sdk/v0.2.1/reference","source_sha256":"81ec90cee0d6e2c3a3728b8c3d43100af089c0515713bcc1f6093a1be1b6354b","source_url":"https://owlshare.io/v1/sdk/v0.2.1/source.tar.gz","version":"v0.2.1"},"type":"owlshare-service-connect"}
