suhaniawasthi's picture
Upload folder using huggingface_hub
6ff09d1 verified
Raw
History Blame Contribute Delete
15.8 kB
"""Ground-truth protocol specification.
This module is the canonical description of what the mock protocol server does.
It is consumed by:
- protocol_server.py (to drive the FastAPI route handlers)
- matcher.py (to score the agent's belief graph)
- designer.py (to know what to mutate)
The agent NEVER sees this spec. The whole task of Protocol One is for the
agent to reconstruct an approximation of this dict by probing the server.
Invariants:
- Exactly 18 endpoints
- Two resources (User, Document) with state machines
- Bearer auth with five named scopes
- Stable, alphabetically-sortable structure (matcher relies on determinism,
not on dict ordering, but it is friendly to humans reading rollouts).
"""
SPEC: dict = {
"auth": {
"type": "bearer",
"scopes": ["users:read", "users:write", "docs:read", "docs:write", "admin"],
},
"resources": [
{
"name": "User",
"fields": [
{"name": "id", "type": "string", "required": True},
{"name": "email", "type": "string", "required": True},
{"name": "role", "type": "string", "required": True, "enum": ["member", "admin"]},
{"name": "status", "type": "string", "required": True, "enum": ["active", "suspended"]},
{"name": "created_at", "type": "timestamp", "required": True},
],
"state_machine": {
"initial": "active",
"states": ["active", "suspended"],
"transitions": [
{"from": "active", "to": "suspended", "via": "POST /users/{id}/suspend"},
{"from": "suspended", "to": "active", "via": "POST /users/{id}/restore"},
],
},
},
{
"name": "Document",
"fields": [
{"name": "id", "type": "string", "required": True},
{"name": "title", "type": "string", "required": True},
{"name": "body", "type": "string", "required": False},
{"name": "owner_id", "type": "string", "required": True},
{"name": "state", "type": "string", "required": True,
"enum": ["draft", "published", "archived"]},
],
"state_machine": {
"initial": "draft",
"states": ["draft", "published", "archived"],
"transitions": [
{"from": "draft", "to": "published", "via": "POST /docs/{id}/publish"},
{"from": "published", "to": "archived", "via": "POST /docs/{id}/archive"},
# archived -> anything is forbidden; agent must discover this
],
},
},
],
"endpoints": [
# 1
{
"id": "list_users",
"method": "GET",
"path": "/users",
"auth_required": True,
"auth_scope": "users:read",
"query_params": [
{"name": "limit", "type": "int", "required": False, "default": 20, "max": 100},
{"name": "cursor", "type": "string", "required": False},
{"name": "role", "type": "string", "required": False, "enum": ["member", "admin"]},
],
"responses": {
"200": {"shape": "list<User>", "has_pagination": True},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"422": {"shape": "error", "when": "invalid_role_filter_or_limit_too_high"},
},
"aliases": [],
},
# 2
{
"id": "create_user",
"method": "POST",
"path": "/users",
"auth_required": True,
"auth_scope": "users:write",
"body_fields": [
{"name": "email", "type": "string", "required": True},
{"name": "role", "type": "string", "required": False, "default": "member",
"enum": ["member", "admin"]},
],
"responses": {
"201": {"shape": "User"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"409": {"shape": "error", "when": "email_exists"},
"422": {"shape": "error", "when": "invalid_email_or_role"},
},
"aliases": [],
},
# 3
{
"id": "get_user",
"method": "GET",
"path": "/users/{id}",
"auth_required": True,
"auth_scope": "users:read",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "User"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
},
"aliases": ["/users/me"], # /users/me resolves to current user (token-scoped)
},
# 4
{
"id": "update_user",
"method": "PATCH",
"path": "/users/{id}",
"auth_required": True,
"auth_scope": "users:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"body_fields": [
{"name": "email", "type": "string", "required": False},
{"name": "role", "type": "string", "required": False, "enum": ["member", "admin"]},
],
"responses": {
"200": {"shape": "User"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"422": {"shape": "error", "when": "invalid_role"},
},
"aliases": [],
},
# 5
{
"id": "delete_user",
"method": "DELETE",
"path": "/users/{id}",
"auth_required": True,
"auth_scope": "users:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "ack"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"410": {"shape": "error", "when": "already_deleted"}, # idempotent: 2nd call
},
"aliases": [],
},
# 6
{
"id": "suspend_user",
"method": "POST",
"path": "/users/{id}/suspend",
"auth_required": True,
"auth_scope": "users:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "User"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"409": {"shape": "error", "when": "invalid_state_transition"},
},
"aliases": [],
},
# 7
{
"id": "restore_user",
"method": "POST",
"path": "/users/{id}/restore",
"auth_required": True,
"auth_scope": "users:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "User"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"409": {"shape": "error", "when": "invalid_state_transition"},
},
"aliases": [],
},
# 8
{
"id": "list_user_documents",
"method": "GET",
"path": "/users/{id}/documents",
"auth_required": True,
"auth_scope": "docs:read",
"path_params": [{"name": "id", "type": "string", "required": True}],
"query_params": [
{"name": "state", "type": "string", "required": False,
"enum": ["draft", "published", "archived"]},
],
"responses": {
"200": {"shape": "list<Document>"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
},
"aliases": [],
},
# 9
{
"id": "list_documents",
"method": "GET",
"path": "/docs",
"auth_required": True,
"auth_scope": "docs:read",
"query_params": [
{"name": "limit", "type": "int", "required": False, "default": 20, "max": 100},
{"name": "state", "type": "string", "required": False,
"enum": ["draft", "published", "archived"]},
],
"responses": {
"200": {"shape": "list<Document>"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
},
"aliases": [],
},
# 10
{
"id": "create_document",
"method": "POST",
"path": "/docs",
"auth_required": True,
"auth_scope": "docs:write",
"body_fields": [
{"name": "title", "type": "string", "required": True},
{"name": "body", "type": "string", "required": False},
],
"responses": {
"201": {"shape": "Document"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"422": {"shape": "error", "when": "missing_title"},
},
"aliases": [],
},
# 11
{
"id": "get_document",
"method": "GET",
"path": "/docs/{id}",
"auth_required": True,
"auth_scope": "docs:read",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "Document"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
},
"aliases": [],
},
# 12
{
"id": "update_document",
"method": "PATCH",
"path": "/docs/{id}",
"auth_required": True,
"auth_scope": "docs:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"body_fields": [
{"name": "title", "type": "string", "required": False},
{"name": "body", "type": "string", "required": False},
],
"responses": {
"200": {"shape": "Document"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"409": {"shape": "error", "when": "not_in_draft_state"},
},
"aliases": [],
},
# 13
{
"id": "delete_document",
"method": "DELETE",
"path": "/docs/{id}",
"auth_required": True,
"auth_scope": "docs:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "ack"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
},
"aliases": [],
},
# 14
{
"id": "publish_document",
"method": "POST",
"path": "/docs/{id}/publish",
"auth_required": True,
"auth_scope": "docs:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "Document"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"409": {"shape": "error", "when": "invalid_state_transition"},
},
"aliases": [],
},
# 15
{
"id": "archive_document",
"method": "POST",
"path": "/docs/{id}/archive",
"auth_required": True,
"auth_scope": "docs:write",
"path_params": [{"name": "id", "type": "string", "required": True}],
"responses": {
"200": {"shape": "Document"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
"404": {"shape": "error", "when": "not_found"},
"409": {"shape": "error", "when": "invalid_state_transition"},
},
"aliases": [],
},
# 16
{
"id": "whoami",
"method": "GET",
"path": "/auth/whoami",
"auth_required": True,
"auth_scope": "users:read",
"responses": {
"200": {"shape": "User"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
},
"aliases": [],
},
# 17
{
"id": "list_scopes",
"method": "GET",
"path": "/auth/scopes",
"auth_required": True,
"auth_scope": "admin",
"responses": {
"200": {"shape": "list<string>"},
"401": {"shape": "error", "when": "missing_or_invalid_token"},
"403": {"shape": "error", "when": "insufficient_scope"},
},
"aliases": [],
},
# 18
{
"id": "health",
"method": "GET",
"path": "/_/health",
"auth_required": False,
"auth_scope": None,
"responses": {
"200": {"shape": "ack"},
},
"aliases": [],
},
],
}
# Tokens that exist on the mock server. Agent gets `INITIAL_TOKEN` in the
# system prompt; other tokens (with different scopes) must be discovered.
TOKENS: dict = {
"token_full": {"scopes": ["users:read", "users:write", "docs:read", "docs:write", "admin"]},
"token_read": {"scopes": ["users:read", "docs:read"]},
"token_write": {"scopes": ["users:write", "docs:write"]},
"token_admin": {"scopes": ["admin"]},
}
INITIAL_TOKEN = "token_full"