Coding Standard
Enforce schema design, implementation process, and script conventions for all SBX code
Tags
Overview
Purpose
Enforce schema design, implementation process, and script conventions for all SBX code
Rules
SCH-001: Never use open/any types. Every object MUST have explicit properties or additionalProperties with typed values.
Open types bypass validation entirely. Without explicit properties, tooling can't validate, autocomplete, or generate types.
Verification: Schema validation: scan for objects without properties. Lint for 'type: any' or 'type: object' without property definitions.
SCH-002: If it's an object, define what keys and values it accepts. No ambiguity.
Ambiguous objects produce ambiguous implementations. Explicit key/value definitions enable codegen and validation.
Verification: Schema review: every object type must have properties or a well-typed additionalProperties.
SCH-003: Define reusable internal types in definitions, reference with $ref.
Duplicated type definitions drift. Centralized definitions in definitions/ section ensure single source of truth.
Verification: Schema lint: check for duplicated type structures that should be extracted to definitions.
SCH-004: External schema references MUST be defined in definitions section first, then referenced via $ref: '#/definitions/name'. Never use external $ref directly in properties.
Direct external $ref creates hidden dependencies. Defining in definitions first makes the dependency explicit and testable.
Verification: Schema lint: scan for $ref values that point to external files directly in properties (not via definitions).
SCH-005: Weak schemas create weak tooling. Be explicit.
Schema quality directly determines tooling quality. Vague schemas produce vague validation, vague codegen, and vague documentation.
Verification: Design review: challenge any schema property that lacks type, constraints, or governance.
SCH-006: Always define rules for schema design instead of adding comment sections.
Comments are invisible to tooling. Rules sections are parseable, enforceable, and discoverable.
Verification: Schema review: rules section present and populated. No standalone comment blocks explaining design choices.
SCH-007: System-level rules belong in schema.yml first, cascade to all entities.
Distributed rules are inconsistent rules. Central governance in schema.yml ensures all entities inherit the same baseline.
Verification: Governance review: entity-specific rules must not contradict schema.yml rules. Schema.yml is authoritative.
SCH-008: Entity IDs are optional. When used, format is {PREFIX}{NUMBER} generated via schema generate-id.
Consistent ID format enables cross-referencing and tooling. Optional because not all entities need synthetic IDs.
Verification: CLI validation: sbx schema generate-id produces correct format.
SCH-009: Schema names MUST be unique across entire framework. Use namespaced names when collision risk exists.
Name collisions cause silent file overwrites and broken references. Namespacing prevents collisions proactively.
Verification: CLI check: sbx schema list reports no duplicate names. New schemas checked against existing names.
SCH-010: Properties without changelog are drafts (not yet implemented). No changelog = no implementation expectation.
Distinguishes between designed properties and implemented properties. Prevents premature implementation of draft schemas.
Verification: Schema review: implemented properties must have changelog entries. Draft properties should be marked as such.
SCH-011: Once a property is implemented, any schema change MUST add a changelog entry with timestamp (ISO 8601 UTC) and action.
Schema changes without changelog create invisible drift between schema versions. Timestamps enable drift detection.
Verification: Git hook: detect schema property changes without corresponding changelog entries.
SCH-012: Changelog entries are append-only. Never remove or modify existing entries.
Changelog is an audit trail. Modifying history destroys traceability and trust in the schema evolution record.
Verification: Git diff review: changelog section only has additions, never deletions or modifications to existing entries.
SCH-013: ID prefix derived from schema name using abbreviation algorithm (first letter, consonants, vowels, full name).
Deterministic prefix generation ensures consistent IDs across tools and sessions without manual allocation.
Verification: CLI check: sbx schema generate-id uses abbreviation algorithm. Prefixes are deterministic for a given name.
SCH-014: ID state stored in .runtime/schema-id.yml. Script manages prefix allocation and counters.
Centralized ID state prevents counter collisions and duplicate IDs across concurrent sessions.
Verification: File exists: .runtime/schema-id.yml tracks all allocated prefixes and current counters.
SCH-015: When creating domain-specific schemas that may collide with generic concepts, prefix with domain abbreviation (e.g., prof- for professional).
Domain prefixes provide namespace isolation without requiring a full namespace registry. Prevents subtle name collisions between generic and domain-specific schemas.
Verification: Schema review: domain-specific schemas use abbreviation prefix. No collision with generic concept names.
SCH-016: Compare changelog timestamps against implementation commit dates to detect schema-implementation drift.
Drift between schema changes and implementation creates silent inconsistencies. Timestamp comparison automates drift detection.
Verification: CI check: changelog timestamps within 48h of corresponding implementation commits.
IMP-001: Design object model FIRST: classes, properties, relationships. Deliverable: class diagram.
Implementation without a model is coding by discovery. The model reveals structure issues before they become code issues.
Verification: Process gate: class diagram artifact exists before implementation begins.
IMP-002: Design sequence diagrams for each operation. Deliverable: operation flows.
Sequence diagrams reveal interaction complexity and boundary crossings that class diagrams don't show.
Verification: Process gate: sequence diagram artifacts exist for each operation.
IMP-003: Build e2e tests FIRST (TDD). Write Makefile + fixtures before code.
TDD ensures implementation is testable by design. Makefile-first creates live documentation of expected behavior.
Verification: Process gate: test infrastructure (Makefile, fixtures/) exists before implementation code.
IMP-004: Implement code to pass e2e tests. Follow existing script patterns.
Tests define the contract. Implementing to pass tests prevents scope creep and ensures conformance to specification.
Verification: All e2e tests pass. New code follows patterns from existing implementations.
IMP-005: Add unit tests for gaps: edge cases, error paths not covered by e2e.
E2e tests cover happy paths. Unit tests cover the edge cases, error conditions, and boundary conditions that e2e misses.
Verification: Coverage analysis: edge cases and error paths have dedicated unit tests.
IMP-006: Validate all works: all tests green, integration with existing tools.
Final validation ensures nothing was broken by the new implementation. Integration testing catches compatibility issues.
Verification: CI gate: all tests pass. Integration with existing tooling verified.
IMP-007: All domain services MUST follow the service pattern structure (NewService, CRUD methods, Input types).
Consistent service patterns enable codegen, reduce cognitive load, and make services interchangeable at the interface level.
Verification: Code review: new services follow NewService constructor, CRUD method signatures, and Input struct patterns.
IMP-008: Mutations MUST use explicit Input structs (CreateXInput, UpdateXInput), not raw maps or inline types.
Input structs are self-documenting, validatable, and versionable. Raw maps bypass all compile-time checks.
Verification: Code review: mutation methods accept named Input structs. No map[string]interface{} parameters.
IMP-009: Input validation MUST happen at start of Create/Update methods. Fail fast with wrapped errors.
Early validation prevents partial state changes. Fail-fast with wrapped errors gives clear error context for debugging.
Verification: Code review: first lines of Create/Update validate input. Errors wrapped with fmt.Errorf and %w verb.
IMP-010: Errors MUST be wrapped with context using fmt.Errorf with %w verb for error chain.
Unwrapped errors lose context as they propagate up the call stack. Error chains enable precise debugging.
Verification: Code review: error returns use fmt.Errorf with %w. No bare error returns without context.
IMP-011: Entities MUST follow standard directory patterns ({type}s/{name}/).
Consistent directory conventions enable filesystem scanning for state derivation and tooling discovery.
Verification: CLI check: sbx entities list discovers all entities via directory convention.
IMP-012: YAML schema MUST be defined before implementation. No code without model.
Schema-first development ensures the data model is complete and validated before any code touches it.
Verification: Process gate: schema file exists and validates before implementation PR is opened.
IMP-013: API endpoints MUST follow URL patterns (GET/POST/PUT/DELETE) and response formats from implementation-patterns.yml.
Consistent API patterns enable client codegen and reduce integration friction. Deviation creates per-endpoint learning curves.
Verification: API review: endpoints follow RESTful patterns. Response format matches implementation-patterns.yml.
IMP-014: New implementations SHOULD reference existing examples in pkg/project, pkg/client, pkg/entityschema as canonical patterns.
Existing implementations are battle-tested. Referencing them ensures consistency and reduces reinvention of solved patterns.
Verification: Code review: new service implementations follow patterns established in reference packages.
SCR-001: Every script MUST accept a root directory parameter for file operations.
Root directory parameter enables testability (isolated temp directories) and portability (different workspace locations).
Verification: Code review: script entry point accepts root/base directory argument. No hardcoded absolute paths.
SCR-002: Scripts SHOULD NOT hardcode paths; all paths relative to provided root.
Hardcoded paths couple scripts to a specific machine or directory layout. Relative paths enable portability.
Verification: Code review: grep for absolute path literals. All file operations use paths relative to root parameter.
SCR-003: Root dir parameter enables tests to use isolated temp directories.
Test isolation prevents tests from affecting real workspace data. Temp directories ensure clean test state.
Verification: Test review: test setup creates temp directory and passes it as root. No tests operate on real workspace.
GO-001: Schema types generate Go structs. Manual struct definition is forbidden for schema-backed entities.
Generated structs stay in sync with schema. Manual structs drift, creating discrepancies between schema validation and Go type system.
Verification: Code review: schema-backed Go types are generated, not hand-written. Generation script exists.
GO-002: Go validation rules must match schema.yml constraints exactly. Test parity required.
Divergence between schema constraints and Go validation creates inconsistent behavior between CLI validation and API validation.
Verification: Test: Go validator rejects same inputs that schema validation rejects. Parity test suite exists.
CLI-001: All workspace actions MUST go through sbx CLI. No direct shell scripts or Makefiles for workspace operations.
Single entry point ensures consistent logging, validation, and error handling. Direct scripts bypass governance.
Verification: Process review: workspace operations invoked via sbx commands, not raw scripts.
CLI-002: Internal projects run via 'sbx project run <name>'. Reads project.yml, starts configured services.
Standardized run command enables consistent startup across all projects. project.yml declares dependencies and configuration.
Verification: sbx project run produces correct startup for each configured project.
CLI-003: External clients run via 'sbx client run <name>:<project>'. Reads client.yml, executes in client workspace.
Client isolation prevents cross-contamination. Client-specific configuration in client.yml, not global state.
Verification: sbx client run starts the correct client project with proper isolation.
CLI-004: workspace.sh is deprecated. All orchestration through sbx commands.
Legacy shell orchestration bypasses all SBX governance — no validation, no logging, no port management.
Verification: No references to workspace.sh in active code or documentation.
CLI-005: Client operations support phases: run (dev), build, test, deploy.
Phase-based operations enable consistent lifecycle management across all clients.
Verification: sbx client run/build/test/deploy work for all configured clients.
CLI-006: Environment configuration via adapter CLI. No hardcoded paths in scripts.
Adapters centralize configuration resolution. Hardcoded paths break on different machines and environments.
Verification: Scripts use sbx adapter commands for path/port resolution, not inline values.