# Story 5.1: Fix PLUGIN_METADATA Name Inconsistencies

## Status: Complete

## Priority: Critical

## Estimated Effort: Small (1 day)

## Dependencies: None

## Epic: Plugin System Completion

---

## Context

The plugin audit revealed inconsistencies between the `name` class attribute on plugin classes and the `name` field in `PLUGIN_METADATA`. This creates confusion when users reference plugins by name in configuration.

---

## Problem Statement

Current inconsistencies:

| Plugin Class             | `name` attribute  | `PLUGIN_METADATA["name"]` | Issue                     |
| ------------------------ | ----------------- | ------------------------- | ------------------------- |
| `ContextVarsEnricher`    | `context_vars`    | `context-vars-enricher`   | Suffix and style mismatch |
| `RuntimeInfoEnricher`    | `runtime_info`    | `runtime-info-enricher`   | Suffix and style mismatch |
| `ZeroCopyProcessor`      | `zero_copy`       | `zero-copy`               | Style mismatch            |
| `FieldMaskRedactor`      | `field_mask`      | `field_mask`              | ✅ Consistent             |
| `RegexMaskRedactor`      | `regex_mask`      | `regex_mask`              | ✅ Consistent             |
| `UrlCredentialsRedactor` | `url_credentials` | `url_credentials`         | ✅ Consistent             |
| `StdoutJsonSink`         | `stdout_json`     | `stdout-json`             | Style mismatch            |
| `RotatingFileSink`       | `rotating_file`   | `rotating-file`           | Style mismatch            |
| `HttpSink`               | `http`            | `http`                    | ✅ Consistent             |
| `WebhookSink`            | `webhook`         | `webhook`                 | ✅ Consistent             |

The loader normalizes names (hyphen → underscore, lowercase), but PLUGIN_METADATA is user-facing and should match what users configure.

---

## Acceptance Criteria

### AC1: Consistent Naming Convention

- [ ] All `PLUGIN_METADATA["name"]` values use underscore format (matching class `name` attribute)
- [ ] OR all values use hyphen format (more user-friendly in YAML/env)
- [ ] Decision documented in `docs/plugins/authoring.md`

### AC2: No Suffixes in Names

- [ ] Remove `-enricher`, `-redactor`, `-sink`, `-processor` suffixes from PLUGIN_METADATA
- [ ] Plugin type is already specified in `plugin_type` field

### AC3: Validation at Load Time

- [ ] Add validation warning if `name` attribute differs from `PLUGIN_METADATA["name"]`
- [ ] Emit diagnostic on mismatch (warn level, not error)

### AC4: Documentation Updated

- [ ] `docs/plugins/authoring.md` specifies naming convention
- [ ] Examples in all plugin docs use consistent names

---

## Technical Design

### Decision: Use Underscore Format (Matching Class Attributes)

Rationale:

- Class `name` attribute is the runtime identifier
- Loader already normalizes hyphens to underscores
- Python convention prefers underscores
- Aliases already handle hyphen variants

### Changes Required

#### 1. Update Enricher Metadata

```python
# src/fapilog/plugins/enrichers/context_vars.py
PLUGIN_METADATA = {
    "name": "context_vars",  # Was: "context-vars-enricher"
    # ... rest unchanged
}

# src/fapilog/plugins/enrichers/runtime_info.py
PLUGIN_METADATA = {
    "name": "runtime_info",  # Was: "runtime-info-enricher"
    # ... rest unchanged
}
```

#### 2. Update Processor Metadata

```python
# src/fapilog/plugins/processors/zero_copy.py
PLUGIN_METADATA = {
    "name": "zero_copy",  # Was: "zero-copy"
    # ... rest unchanged
}
```

#### 3. Update Sink Metadata

```python
# src/fapilog/plugins/sinks/stdout_json.py
PLUGIN_METADATA = {
    "name": "stdout_json",  # Was: "stdout-json"
    # ... rest unchanged
}

# src/fapilog/plugins/sinks/rotating_file.py
PLUGIN_METADATA = {
    "name": "rotating_file",  # Was: "rotating-file"
    # ... rest unchanged
}

# src/fapilog/plugins/sinks/mmap_persistence.py
PLUGIN_METADATA = {
    "name": "mmap_persistence",  # Was: "mmap-persistence"
    # ... rest unchanged
}
```

#### 4. Add Name Consistency Validation

In `plugins/loader.py`:

```python
def _validate_name_consistency(cls: type, config: dict[str, Any]) -> None:
    """Warn if class name attribute differs from PLUGIN_METADATA name."""
    class_name = getattr(cls, "name", None)

    # Try to get PLUGIN_METADATA from module
    try:
        import importlib
        mod = importlib.import_module(cls.__module__)
        metadata = getattr(mod, "PLUGIN_METADATA", None)
        if metadata and isinstance(metadata, dict):
            meta_name = metadata.get("name")
            if meta_name and class_name:
                if _normalize_plugin_name(class_name) != _normalize_plugin_name(meta_name):
                    diagnostics.warn(
                        "plugins",
                        "plugin name mismatch",
                        class_name=class_name,
                        metadata_name=meta_name,
                        plugin=cls.__name__,
                    )
    except Exception:
        pass
```

---

## Test Plan

### Unit Tests

1. **test_plugin_name_consistency.py**
   - Test all built-in plugins have matching name/PLUGIN_METADATA
   - Test validation warning emitted on mismatch
   - Test normalization still works for aliases

### Integration Tests

1. **test_plugin_loading_by_name.py**
   - Test loading by underscore name
   - Test loading by hyphen alias
   - Test both resolve to same plugin

---

## Migration Notes

- This is NOT a breaking change due to name normalization
- Users who configured `context-vars-enricher` will see a deprecation warning
- Add aliases for old names during transition period

---

## Documentation Updates

1. Update `docs/plugins/authoring.md`:

   ```markdown
   ## Naming Convention

   Plugin names should use lowercase with underscores (snake_case):

   - Good: `field_mask`, `rotating_file`, `runtime_info`
   - Avoid: `field-mask-redactor`, `RotatingFileSink`

   The `name` class attribute and `PLUGIN_METADATA["name"]` must match.
   Hyphen variants are automatically supported as aliases.
   ```

2. Update all plugin documentation examples to use underscore format

---

## Related Stories

- Story 5.0: Wire processors into pipeline
- Story 5.4: Plugin testing guide (include name validation)
