Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/style.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Style Guide Check

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

jobs:
style:
runs-on: blacksmith-4vcpu-ubuntu-2404

steps:
- uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Run lexicon style guide checker
run: npm run style:check
108 changes: 108 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Contributing to Hypercerts Lexicon

Thank you for your interest in contributing! This guide covers the
contribution process. For technical details about the codebase, see
[AGENTS.md](AGENTS.md).

## Quick Start

```bash
# Fork and clone the repository
git clone https://github.com/your-username/hypercerts-lexicon.git
cd hypercerts-lexicon

# Install dependencies
npm install

# Verify setup
npm run check
```

## Making Changes

### Using AI Agents (Recommended)

The easiest way to contribute is using an AI agent that respects the
guidance in [AGENTS.md](AGENTS.md). The agent will handle code
generation, formatting, and changesets automatically.

### Manual Changes

If making changes manually, follow the workflow in [AGENTS.md § Adding
/ modifying a lexicon](AGENTS.md#adding--modifying-a-lexicon).

**Key points:**

- Never edit `generated/` or `dist/` directories directly
- Run `npm run gen-api` after modifying lexicon JSON files
- Run `npm run format` before committing
- Run `npm run check` to validate everything
- **Always create a changeset** for public API changes

## Changesets (Required)

Create a changeset for any user-facing changes:

```bash
npm run changeset
```

Follow the prompts to select version bump type and describe
changes. See [AGENTS.md § Versioning](AGENTS.md#versioning) for
details.

## Pull Request Process

1. **Target the `develop` branch** (not `main`)
2. **Ensure all checks pass**: `npm run check`
3. **Include a changeset** if required
4. **Write clear commit messages** using conventional commit format
5. **Respond to review feedback** promptly

### Before Submitting

```bash
npm run format # Format code
npm run check # Validate everything passes
```

## Code Quality Standards

- **Formatting**: Run `npm run format` (uses Prettier + EditorConfig)
- **Linting**: Run `npm run lint`
- **Type checking**: Run `npm run typecheck`
- **Lexicon style**: Run `npm run style:check`

See [LEXICON_STYLE_GUIDE.md](LEXICON_STYLE_GUIDE.md) for lexicon best
practices.

## Development Commands

See [AGENTS.md § Development Commands](AGENTS.md#development-commands)
for the complete list of available npm scripts.

## Project Structure

See [AGENTS.md § Project Structure](AGENTS.md#project-structure) for
directory layout and file organization.

## Getting Help

- **Issues**: [GitHub Issues](https://github.com/hypercerts-org/hypercerts-lexicon/issues)
- **Discussions**: [GitHub Discussions](https://github.com/hypercerts-org/hypercerts-lexicon/discussions)
- **Documentation**: [README.md](README.md), [AGENTS.md](AGENTS.md), [SCHEMAS.md](SCHEMAS.md)

## Release Process

**Contributors only create changesets.** Releases are handled by
maintainers via GitHub Actions on the `develop` (beta) and `main`
(stable) branches.

## License

Contributions are licensed under the MIT License.

---

**Thank you for contributing!** Your work helps make the Hypercerts
protocol better for everyone.
193 changes: 193 additions & 0 deletions LEXICON_STYLE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# ATProto Lexicon Style Guide

This document summarizes the ATProto Lexicon Style Guide rules that are checked by our automated checker. For the complete guide, visit: https://atproto.com/guides/lexicon-style-guide

## Key Style Rules

### 1. Naming Conventions

#### Lexicon IDs (NSIDs)

- **Format**: Reverse-DNS notation (e.g., `org.hypercerts.claim.activity`)
- **Case**: All lowercase
- **Segments**: Use descriptive, concise names
- **Avoid**: Numbers in authority segments, generic names like "item" or "thing"

#### Record Keys

- **Recommendation**: Use `any` for most record keys to allow flexible client-side naming
- **TIDs**: When using TIDs (Timestamp IDs), ensure they're appropriate for the use case
- **Literal keys**: Only use for singleton records or very specific use cases

#### Property Names

- **Format**: camelCase
- **Clarity**: Use clear, descriptive names
- **Avoid**: Abbreviations unless widely understood
- **Consistency**: Use consistent terminology across related lexicons

### 2. Descriptions

#### Lexicon Descriptions

- **Completeness**: Every lexicon should have a clear description
- **Detail**: Explain the purpose and usage
- **Context**: Provide enough information for developers to understand

#### Property Descriptions

- **Required**: All properties should have descriptions
- **Clarity**: Explain what the property represents and how it should be used
- **Format hints**: Include format expectations when relevant

#### Definition Descriptions

- **Coverage**: All definitions (objects, arrays, etc.) should have descriptions
- **Purpose**: Explain the role of the definition in the schema

### 3. Schema Design

#### Type Selection

- **Primitives**: Use appropriate primitive types (string, integer, boolean)
- **Formats**: Apply format constraints (datetime, uri, cid, did, etc.)
- **Refs**: Use refs for reusable types and relationships
- **Unions**: Use unions when a property can be one of several types

#### Constraints

- **String lengths**: Always set maxLength for strings
- **maxGraphemes**: Consider using maxGraphemes for user-visible text
- **Array constraints**: Consider maxLength for arrays
- **Required fields**: Mark truly required fields, keep optional what can be optional

#### Blob Handling

- **Size limits**: Always specify maxSize for blobs
- **MIME types**: Specify accepted MIME types with the `accept` property
- **Documentation**: Document blob size limits and types clearly

### 4. Relationships and References

#### Strong References

- **Usage**: Use `com.atproto.repo.strongRef` for references to other records
- **Documentation**: Clearly document what type of record is expected
- **Validation**: Specify the expected lexicon type in the description

#### Arrays of References

- **Consistency**: Use consistent patterns for arrays of references
- **Documentation**: Explain the relationship and cardinality

### 5. Timestamps

#### DateTime Fields

- **Format**: Always use `format: "datetime"` for timestamp fields
- **Naming**: Use clear names like `createdAt`, `updatedAt`, `publishedAt`
- **Requirement**: Mark as required when appropriate
- **Documentation**: Explain when the timestamp should be set

### 6. Common Patterns

#### Created At

- **Standard**: Include a `createdAt` field for records
- **Type**: `string` with `format: "datetime"`
- **Description**: "Client-declared timestamp when this record was originally created"

#### Updated At

- **Usage**: Include `updatedAt` for mutable records
- **Type**: `string` with `format: "datetime"`
- **Description**: "Client-declared timestamp when this record was last updated"

#### Versioning

- **Consideration**: Think about versioning strategy for evolving schemas
- **Migration**: Document breaking changes

### 7. Validation and Constraints

#### String Validation

- **maxLength**: Always set for strings (prevents abuse)
- **maxGraphemes**: Use for user-facing text (better UX for internationalization)
- **Patterns**: Use regex patterns when format validation is needed

#### Number Validation

- **Range**: Consider minimum and maximum values
- **Integers**: Use integer type when fractional values don't make sense

#### Required vs Optional

- **Conservative**: Only mark as required if truly necessary
- **Flexibility**: Allow optional fields for future extensibility
- **Documentation**: Explain when optional fields should be used

### 8. Documentation Best Practices

#### Inline Documentation

- **Comprehensive**: Document all types, properties, and constraints
- **Examples**: Include example values in descriptions when helpful
- **Context**: Explain relationships and dependencies

#### External Documentation

- **README**: Maintain high-level documentation
- **Migration guides**: Document schema changes and migrations
- **Examples**: Provide usage examples

### 9. Lexicon Organization

#### File Structure

- **Grouping**: Group related lexicons in namespaces
- **Definitions**: Use `defs.json` for shared definitions
- **Modularity**: Keep lexicons focused and modular

#### Dependencies

- **Explicit**: Clearly document dependencies on other lexicons
- **Minimal**: Minimize cross-lexicon dependencies
- **Standard**: Use standard ATProto lexicons when appropriate

### 10. Security and Privacy

#### Data Sensitivity

- **PII**: Be careful with personally identifiable information
- **Access control**: Consider who can read/write records
- **Validation**: Validate all input data

#### Size Limits

- **DoS prevention**: Set appropriate size limits on all fields
- **Blob limits**: Be conservative with blob size limits
- **Array limits**: Limit array sizes to prevent abuse

## Automated Checks

The `style:check` script checks for:

1. ✅ All lexicons have descriptions
2. ✅ All properties have descriptions
3. ✅ All definitions have descriptions
4. ✅ String properties have maxLength constraints
5. ✅ Blob properties have maxSize and accept properties
6. ✅ DateTime fields use the correct format
7. ✅ Property names use camelCase
8. ✅ Required fields are properly marked
9. ✅ StrongRef usage is documented
10. ✅ Lexicon IDs follow naming conventions

## Running the Checker

```bash
npm run style:check
```

This will check all lexicons in the `lexicons/` directory and report any style guide violations.
1 change: 1 addition & 0 deletions opencode.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"npm run list": "allow",
"npm run prepublishOnly": "deny",
"npm run release": "deny",
"npm run style": "allow",
"npm run test": "allow",
"npm run test:watch": "allow",
"npm run typecheck": "allow",
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"eslint": "eslint generated/exports.ts",
"typecheck": "tsc --noEmit",
"clean": "rm -rf dist generated",
"style:check": "node ./scripts/check-lexicon-style.js",
"prepublishOnly": "npm run check",
"changeset": "changeset",
"version-packages": "changeset version && npm install --package-lock-only",
Expand Down
Loading
Loading