Demo: a DevContract engagement end-to-end
A walkthrough of the full three-phase DevContract model. Starting from a devcontract.json file, through agent injection at session start, to clause queries during execution, to the signed evidence receipt at delivery.
This demo uses the ticketyboo.dev free_tier_python contract — the actual contract governing this codebase.
Phase 1 — Contract
The contract file
Phase 1 · ContractThe client places .tickety/devcontract.json in the project root. This is the actual ticketyboo.dev contract:
{
"contract_version": "1.0",
"project": "ticketyboo.dev",
"parties": {"client": "fenderfonic", "contractor": "claude-code"},
"stack": {
"language": "python", "language_version": "3.12",
"runtime": "aws_lambda", "region": "eu-north-1",
"forbidden_services": ["ec2", "fargate", "lightsail", "rds"]
},
"cost": {
"budget_envelope": "aws_free_tier",
"forbidden_resources": ["nat_gateway", "rds", "secrets_manager", "kms_cmk", "elastic_ip"],
"approved_exceptions": ["route53_hosted_zone"]
},
"security": {
"auth_mechanism": "cognito_jwt",
"secrets_store": "ssm_parameter_store",
"forbidden_secrets_locations": ["env_vars", "source_code", "config_files"],
"owasp_compliance": true, "production_deploy_gate": true
},
"quality": {
"type_hints": "required", "test_coverage_min": 80,
"logging_standard": "module_logger_only"
},
"compliance": {"frameworks": ["gdpr"], "right_to_erasure": "hard_delete_only"},
"definition_of_done": {
"tests_pass": true, "coverage_met": true, "no_contract_violations": true,
"scan_gates": [
{"category": "secret", "severity": "critical", "blocking": true},
{"category": "sast", "severity": "high", "blocking": true}
]
}
}tickety-ai injects the contract at session start
Phase 1 · ContractloadSteeringFiles() reads the JSON, calls renderContract(), and prepends the result as the first block of the system prompt. Claude reads this before any task or steering file:
== ACTIVE DEVCONTRACT (v1.0) ==
Project: ticketyboo.dev | Client: fenderfonic | Contractor: claude-code
STACK: python 3.12 | Runtime: aws_lambda | Region: eu-north-1
FORBIDDEN SERVICES: ec2, fargate, lightsail, rds
COST ENVELOPE: aws_free_tier
Forbidden resources: nat_gateway, rds, secrets_manager, kms_cmk, elastic_ip
Approved exceptions: route53_hosted_zone
SECURITY:
Auth: cognito_jwt
Secrets: ssm_parameter_store ONLY
Never store secrets in: env_vars, source_code, config_files
OWASP compliance: REQUIRED
Production deploy: REQUIRES HUMAN APPROVAL
QUALITY:
Type hints: REQUIRED on all functions
Coverage minimum: 80%
Logging: module_logger_only — no print()
COMPLIANCE: GDPR
Data deletion: hard_delete_only — never soft-delete
DEFINITION OF DONE:
✓ tests_pass | ✓ coverage_met | ✓ no_contract_violations | ✓ evidence_generated
Scan gates: secret:critical (blocking), sast:high (blocking)
== END CONTRACT — you are operating under these terms ==Claude acknowledges the contract
Phase 1 · ContractBefore any work begins, Claude acknowledges the terms:
I've read the active DevContract for ticketyboo.dev.
I'm working under these terms:
- Stack: Python 3.12, AWS Lambda, eu-north-1
- No EC2, Fargate, Lightsail, or RDS — ever
- All secrets in SSM Parameter Store only — not env vars, not source code
- AWS Free Tier constraints: no Secrets Manager, no NAT gateways, no KMS CMKs
- GDPR: hard delete only, no soft delete
- Definition of done: tests pass, 80% coverage, secret:critical and sast:high scan gates pass
I'll consult these constraints before every material decision. Ready to begin.Phase 2 — Execution
Clause query: secrets handling
Phase 2 · ExecutionThe client asks Claude to add a Stripe API key to the Lambda function. Claude consults the contract before deciding:
User: Add the Stripe API key to the payment Lambda.
Claude: Consulting contract clause security.secrets_store:
- secrets_store: ssm_parameter_store ONLY
- forbidden_secrets_locations: [env_vars, source_code, config_files]
I cannot set this as a Lambda environment variable or hardcode it.
I'll read it from SSM Parameter Store at runtime:
import boto3
def _get_stripe_key() -> str:
ssm = boto3.client("ssm", region_name="eu-north-1")
response = ssm.get_parameter(
Name="/ticketyboo/prod/stripe_secret_key",
WithDecryption=True
)
return response["Parameter"]["Value"]
The SSM parameter must be created manually by a human with production access
(production_deploy_gate: REQUIRES HUMAN APPROVAL applies here).
Evidence logged: query approved, action taken per security.secrets_store clause.Clause query: cost — forbidden resource denied
Phase 2 · ExecutionThe client asks Claude to add a NAT Gateway for private subnet egress:
User: Add a NAT Gateway so the Lambda can reach the internet from a private subnet.
Claude: Contract violation — cannot proceed.
Clause: cost.forbidden_resources
Forbidden resource: nat_gateway
Reason: NAT Gateways cost ~$32/month minimum — this violates the aws_free_tier
budget envelope.
Alternative within contract terms: Lambda in the default VPC does not need a NAT
Gateway for internet egress. If a private subnet is required, use a VPC endpoint
for AWS services (some types are free) or reconsider the architecture.
Evidence logged: query denied per cost.forbidden_resources clause.
ContractViolation would be raised if this resource were created.Phase 3 — Delivery
Gatekeep runs scan gates at PR time
Phase 3 · DeliveryAt PR time, Gatekeep evaluates the definition_of_done.scan_gates:
Gatekeep scan results:
secret:critical → 0 findings → PASS ✓
sast:high → 0 findings → PASS ✓
coverage → 84% → PASS ✓ (threshold: 80%)
tests → 47 passed → PASS ✓
definition_of_done: ALL CRITERIA METSigned evidence bundle produced
Phase 3 · DeliveryGatekeep assembles the evidence bundle and signs it against the contract hash:
{
"contract_id": "ticketyboo.dev-2026-04-01",
"contractor": "claude-code",
"client": "fenderfonic",
"contract_hash": "a7f3c2d1e9b4580f3e2a1c9d8b7f6e5d4c3b2a19...",
"engagement_start": "2026-04-01T08:00:00Z",
"engagement_end": "2026-04-01T09:15:00Z",
"contract_queries": [
{
"timestamp": "2026-04-01T08:22:11Z",
"query": "Add the Stripe API key to the payment Lambda",
"clause": "security.secrets_store",
"verdict": "allow",
"action_taken": "Read from SSM Parameter Store SecureString at runtime"
},
{
"timestamp": "2026-04-01T08:47:33Z",
"query": "Add a NAT Gateway for private subnet egress",
"clause": "cost.forbidden_resources",
"verdict": "deny",
"action_taken": "Denied. Alternative architecture proposed using default VPC."
}
],
"clause_results": [
{"clause": "stack", "status": "pass"},
{"clause": "cost", "status": "pass"},
{"clause": "security", "status": "pass"},
{"clause": "quality", "status": "pass"},
{"clause": "compliance", "status": "pass"},
{"clause": "definition_of_done", "status": "pass"}
],
"violations": [],
"overall_verdict": "contract_fulfilled",
"signature": "9b2d3e4f1c7a8b5d2f1e9c3a7b4d8e2f..."
}✓ contract_fulfilled — the engagement is complete and the evidence is signed.
What happens with a violation
Violation scenario: secret detected in source code
Phase 3 · DeliveryIf the Gatekeep secret scan finds a hardcoded credential, the evidence bundle records a ContractViolation and the verdict flips:
{
"violations": [
{
"clause_category": "security",
"clause_id": "security.forbidden_secrets_locations",
"clause_description": "Secrets must not appear in source code",
"violated_by": "api/handler.py line 14: STRIPE_KEY = 'sk_live_4xRt...'",
"evidence_ref": "scan-finding-secret-001",
"severity": "critical",
"remediation": "Remove hardcoded key. Read from SSM Parameter Store at runtime.",
"auto_remediation_available": false
}
],
"overall_verdict": "contract_breached",
"signature": "..."
}✗ contract_breached — the PR is blocked. The violation must be remediated before delivery.