# serverless-tag-resources

Serverless Framework plugin to tag all AWS resources. Supports dual tagging (legacy PascalCase + new `datamart:*` format) for transition periods.

## Features

- Tags all resources created by Serverless Framework
- Tags resources in the `resources` section
- Handles dict-based tag resources (SSM Parameter, API GW V2, Glue, Batch)
- Post-deploy tagging for RDS Clusters, Firehose, EC2 related resources
- Auto-generates `Stage` / `datamart:environment` from deployment stage
- Auto-generates `Resource` / `datamart:resource` from CloudFormation LogicalID
- Optional tag validation against allowed domains
- AWS SDK v3

## Installation

```
npm i serverless-tag-resources
```

Add to plugins:

```yaml
plugins:
  - serverless-tag-resources
```

## Configuration

### Tags (provider.stackTags)

```yaml
provider:
  stackTags:
    # Legacy tags (maintained for backwards compatibility)
    CostCenter: getdata
    BusinessUnit: getdata-cl
    Service: ${self:service}
    Component: api
    Customer: common

    # New datamart:* tags
    datamart:cost-center: getdata
    datamart:business-unit: getdata-cl
    datamart:service: ${self:service}
    datamart:component: api
    datamart:finops-scope: runtime
    datamart:data-classification: confidential
    datamart:criticality: high
    datamart:team: platform
```

The plugin auto-adds these tags (no need to specify):
- `Stage` / `datamart:environment` — set to the deployment stage
- `Resource` / `datamart:resource` — set to the CloudFormation LogicalID

### Validation (optional)

Enable tag validation to enforce required tags and allowed values:

```yaml
custom:
  datamart:
    validation: true
```

When enabled, deployment fails if required `datamart:*` tags are missing or have invalid values.

**Required tags**: `datamart:cost-center`, `datamart:finops-scope`, `datamart:data-classification`, `datamart:criticality`, `datamart:team`

**Validated values**:
- `datamart:finops-scope`: runtime, compliance, security, scraping, ai, devtools, infrastructure
- `datamart:environment`: prod, homo, qa, dev, sandbox, dr
- `datamart:data-classification`: public, internal, confidential, restricted
- `datamart:criticality`: critical, high, medium, low
- `datamart:cost-center`: datamart, getdata, connect, vizdata, legalbase, facesign, keyshield, lendbot, jscipher, atlas, openfinance, payments, operations

## How it works

### Hook 1: before:package:finalize

Mutates the CloudFormation template to inject tags into all supported resources before deployment. Handles both list-based (`[{Key, Value}]`) and dict-based (`{key: value}`) tag formats depending on the resource type.

### Hook 2: after:deploy:deploy

Tags resources that need post-deploy API calls:
- SSM Parameters (AddTagsToResource)
- Pinpoint Apps (TagResource)
- API Gateway V2 (Api, Stage, DomainName, VpcLink)
- RDS Clusters (AddTagsToResource)
- Kinesis Firehose (TagDeliveryStream)
- EC2 Instances + related resources (EBS volumes, ENIs, EIPs, Security Groups)

## Development

```bash
npm install
npm test
npm run test:verbose
npm run test:coverage
```

## Changelog

### v3.0.0 (April 2026)
- Migrated to AWS SDK v3
- Modular architecture (src/ directory)
- Dual tag support: legacy PascalCase + datamart:* format
- Auto-generated `datamart:environment` and `datamart:resource` tags
- Optional tag validation with domain enforcement
- Fixed: Stage tag was never added to list-based resources (concat bug)
- Fixed: forEach+async pattern (promises were not awaited)
- Fixed: dict-based resources now tagged in CF template (was commented out)
- Fixed: Glue::Crawler contradiction (was in both supported and unsupported lists)
- Added Jest test suite (60+ tests)
- Removed unused helpers (awsCloudFormation.js, awsSSM.js)

### v2.5.2
- Last version before refactor
- Single file architecture (index.js)
- AWS SDK v2

## License

ISC
