docs: add Claude AI assistant rules and configuration
All checks were successful
CVE Scan & Docker Build / security-scan (push) Successful in 45s
CVE Scan & Docker Build / build-and-push (push) Successful in 1m53s

Add comprehensive rule documentation for AI-assisted development covering
authentication surfaces, outbound-call safety invariants, and other project
conventions to guide Claude's understanding of critical system behaviors.
This commit is contained in:
2026-07-28 19:01:38 -04:00
parent 016d8be71d
commit 4a3c14d4af
40 changed files with 2851 additions and 202 deletions

View File

@@ -14,6 +14,7 @@ from sqlalchemy import (
Column,
DateTime,
Float,
ForeignKey,
Integer,
String,
Text,
@@ -153,6 +154,48 @@ class RecordingRecord(Base):
return f"<Recording {self.id} call={self.call_id} {self.path}>"
class User(Base):
"""An SSO-provisioned identity. The gateway is owner-only: the single
owner is the user whose `name` matches settings.owner_name; everyone else
is created on first login but reaches nothing (403 on every surface)."""
__tablename__ = "users"
id = Column(String, primary_key=True) # uuid4().hex, set in Python
name = Column(String, nullable=False) # Casdoor username — owner-match key
display_name = Column(String, nullable=True) # Casdoor display name (UI only)
email = Column(String, nullable=True, unique=True)
casdoor_sub = Column(String, nullable=True, unique=True) # OIDC subject claim
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
def __repr__(self) -> str:
return f"<User {self.id} {self.name}>"
class PersonalAccessToken(Base):
"""Long-lived bearer token for API/MCP clients (Claude Desktop, Cline)
that can't refresh a JWT. Plaintext is shown once at creation; only the
SHA-256 hash is persisted. Soft-revoked by setting revoked_at."""
__tablename__ = "personal_access_tokens"
id = Column(String, primary_key=True) # uuid4().hex
user_id = Column(
String, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
)
name = Column(String, nullable=False)
token_hash = Column(String, nullable=False, unique=True, index=True)
token_prefix = Column(String, nullable=False) # for display, not a secret
created_at = Column(DateTime, default=func.now())
last_used_at = Column(DateTime, nullable=True)
expires_at = Column(DateTime, nullable=True)
revoked_at = Column(DateTime, nullable=True)
def __repr__(self) -> str:
return f"<PersonalAccessToken {self.id} user={self.user_id}>"
# ============================================================
# Engine & Session
# ============================================================