Canonical Repository Structure#

The canonical repository follows a specific directory layout that supports multiple schema formats and versioning strategies.

Complete Directory Structure#

apis/
├── buf.yaml                 # org-wide lint/breaking policy
├── buf.work.yaml            # workspace aggregating version dirs
├── CODEOWNERS               # per-path ownership
├── catalog/
│  └── catalog.yaml          # generated index of APIs/owners/tags
├── proto/                   # Protocol Buffers
│  └── payments/
│     └── ledger/
│        ├── go.mod          # v1 module: module github.com/<org>/apis/proto/payments/ledger
│        ├── v1/
│        │  └── ledger.proto # package <org>.payments.ledger.v1
│        └── v2/
│           ├── go.mod       # v2 module: module github.com/<org>/apis/proto/payments/ledger/v2
│           └── ledger.proto # package <org>.payments.ledger.v2
├── openapi/                 # OpenAPI specifications
│  └── users/
│     └── v1/
│        ├── go.mod
│        └── users.yaml
├── avro/                    # Avro schemas
│  └── events/
│     └── v1/
│        ├── go.mod
│        └── user-events.avsc
├── jsonschema/              # JSON Schema definitions
│  └── config/
│     └── v1/
│        ├── go.mod
│        └── app-config.json
└── parquet/                 # Parquet schemas
   └── analytics/
      └── v1/
         ├── go.mod
         └── events.parquet

Key Configuration Files#

buf.yaml (Organization-wide Policy)#

version: v2
lint:
  use: [STANDARD]
  except:
    - PACKAGE_DIRECTORY_MATCH  # Allow flexible directory structure
breaking:
  use: [FILE, WIRE]
  except:
    - FIELD_SAME_JSON_NAME     # Allow field name changes

buf.work.yaml (Workspace Configuration)#

version: v1
directories:
  - proto/**/v1
  - proto/**/v2
  # Add v3, v4, etc. as needed

CODEOWNERS (Per-API Ownership)#

# Global fallback
* @org/api-governance

# Domain-specific ownership
/proto/payments/ @org/payments-team
/proto/users/ @org/identity-team
/openapi/gateway/ @org/platform-team

# Schema format ownership
/avro/ @org/data-engineering
/parquet/ @org/analytics-team

Versioning & Go Modules#

Semantic Import Versioning#

APX follows Go’s semantic import versioning:

  • v1 modules: No /v1 suffix in module path

    • module github.com/<org>/apis/proto/payments/ledger

  • v2+ modules: Include /vN suffix

    • module github.com/<org>/apis/proto/payments/ledger/v2

Directory vs Package vs Module#

Directory Structure
proto/payments/ledger/
├── v1/ (files)
└── v2/ (files)
Proto Package Names
<org>.payments.ledger.v1
<org>.payments.ledger.v2
Go Module Paths
github.com/<org>/apis/proto/payments/ledger (v1)
github.com/<org>/apis/proto/payments/ledger/v2

Example go.mod Files#

v1 module (no version suffix):

module github.com/myorg/apis/proto/payments/ledger

go 1.21

v2 module (with version suffix):

module github.com/myorg/apis/proto/payments/ledger/v2

go 1.21

Tagging Strategy#

Subdirectory Tags#

APX uses subdirectory tags for each API version:

# v1 releases
proto/payments/ledger/v1.0.0
proto/payments/ledger/v1.2.3

# v2 releases  
proto/payments/ledger/v2.0.0
proto/payments/ledger/v2.1.0

# Other formats
openapi/users/v1.0.0
avro/events/v1.5.0

Tag Protection#

Protect tag patterns to ensure only CI creates tags:

  • proto/**/v* - Protocol Buffer APIs

  • openapi/**/v* - OpenAPI specifications

  • avro/**/v* - Avro schemas

  • jsonschema/**/v* - JSON schemas

  • parquet/**/v* - Parquet schemas

Catalog Generation#

The catalog/catalog.yaml file is automatically generated by CI and provides searchable metadata:

version: 1
generated_at: "2024-01-15T10:30:00Z"

apis:
  - path: proto/payments/ledger
    kind: proto
    latest_version: v1.2.3
    description: "Ledger service for payment processing"
    owners: ["@org/payments-team"]
    tags:
      - v1.0.0
      - v1.1.0
      - v1.2.3
    
  - path: openapi/users  
    kind: openapi
    latest_version: v1.0.0
    description: "User management REST API"
    owners: ["@org/identity-team"]
    tags:
      - v1.0.0

This catalog enables:

  • apx search functionality

  • API discovery and browsing

  • Automated documentation generation

  • Dependency analysis

Multi-Format Considerations#

Format-Specific Directories#

Each schema format has its own top-level directory:

  • proto/: Protocol Buffers with buf integration

  • openapi/: OpenAPI 3.0+ specifications

  • avro/: Avro schema definitions

  • jsonschema/: JSON Schema validation rules

  • parquet/: Parquet schema definitions

Shared Tooling#

While directories are separate, APX provides unified tooling:

# Works across all formats
apx lint          # Format-specific linting
apx breaking      # Format-specific breaking change detection  
apx search        # Search across all APIs
apx gen <lang>    # Code generation for supported formats

Best Practices#

Directory Naming#

  • Use kebab-case for directory names: user-service, payment-gateway

  • Group related APIs under common domains: payments/, users/, analytics/

  • Keep names concise but descriptive

Ownership Boundaries#

  • Assign clear ownership via CODEOWNERS

  • One team per API path for accountability

  • API governance team as fallback owners

Versioning Strategy#

  • Start with v1, add v2 only when introducing breaking changes

  • Keep v1 maintained until consumers migrate

  • Use semantic versioning for all releases

Documentation#

  • Include README.md in each API directory

  • Document breaking changes in CHANGELOG.md

  • Use proto comments for API documentation