{"id":30615640,"url":"https://github.com/alexfalkowski/bezeichner","last_synced_at":"2026-06-27T07:00:54.273Z","repository":{"id":60976965,"uuid":"533876956","full_name":"alexfalkowski/bezeichner","owner":"alexfalkowski","description":"Bezeichner takes care of identifiers used in your services.","archived":false,"fork":false,"pushed_at":"2026-06-22T21:52:26.000Z","size":3502,"stargazers_count":1,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-06-22T23:10:19.772Z","etag":null,"topics":["cucumber","golang","make","ruby"],"latest_commit_sha":null,"homepage":"https://alexfalkowski.github.io/bezeichner","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexfalkowski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2022-09-07T17:48:59.000Z","updated_at":"2026-06-22T21:13:07.000Z","dependencies_parsed_at":"2026-02-06T00:01:00.319Z","dependency_job_id":"d8b122bf-e382-4a15-b3d7-a11cac387cd6","html_url":"https://github.com/alexfalkowski/bezeichner","commit_stats":{"total_commits":214,"total_committers":2,"mean_commits":107.0,"dds":0.3551401869158879,"last_synced_commit":"306263cd993b7c2a74674dda3d272ffcb4e2ffbd"},"previous_names":[],"tags_count":1171,"template":false,"template_full_name":null,"purl":"pkg:github/alexfalkowski/bezeichner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fbezeichner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fbezeichner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fbezeichner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fbezeichner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexfalkowski","download_url":"https://codeload.github.com/alexfalkowski/bezeichner/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexfalkowski%2Fbezeichner/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34844346,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cucumber","golang","make","ruby"],"created_at":"2025-08-30T08:06:13.231Z","updated_at":"2026-06-27T07:00:54.251Z","avatar_url":"https://github.com/alexfalkowski.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Gopher](assets/gopher.png)\n[![CircleCI](https://circleci.com/gh/alexfalkowski/bezeichner.svg?style=shield)](https://circleci.com/gh/alexfalkowski/bezeichner)\n[![codecov](https://codecov.io/gh/alexfalkowski/bezeichner/graph/badge.svg?token=TDRSV3MGSM)](https://codecov.io/gh/alexfalkowski/bezeichner)\n[![Go Report Card](https://goreportcard.com/badge/github.com/alexfalkowski/bezeichner)](https://goreportcard.com/report/github.com/alexfalkowski/bezeichner)\n[![Go Reference](https://pkg.go.dev/badge/github.com/alexfalkowski/bezeichner.svg)](https://pkg.go.dev/github.com/alexfalkowski/bezeichner)\n[![Stability: Active](https://masterminds.github.io/stability/active.svg)](https://masterminds.github.io/stability/active.html)\n\n# Bezeichner\n\nBezeichner is a small Go service that **generates** and **maps** identifiers, exposed via **gRPC** and **HTTP**.\n\n- gRPC is the primary API surface.\n- HTTP is implemented as an RPC gateway that routes by **gRPC full method name** (so both transports share the same contract).\n\nThe API contract lives in:\n- `api/bezeichner/v1/service.proto`\n\n## Why a service?\n\nDistributed systems often need globally unique identifiers across multiple languages and runtimes. Bezeichner centralizes identifier generation so:\n- you don't re-implement ID generation logic per service/language,\n- you can standardize generator choices per domain/application,\n- you can migrate/translate legacy identifiers via mapping.\n\n## API Overview (v1)\n\nThe v1 service supports:\n- `GenerateIdentifiers`: generate `count` identifiers for a configured `application`\n- `MapIdentifiers`: map a list of identifiers using a configured mapping table\n\nBoth endpoints enforce request-size limits in the domain layer for basic DoS protection (limits are currently 1000 items for both generate count and map list).\n\n## Configuration\n\nBezeichner uses the `go-service` configuration conventions. A representative configuration used by development and feature tests is:\n\n- `test/.config/server.yml`\n\n### Generator configuration\n\nGenerator configuration selects **applications**, each of which has:\n- a `name` (the public application key you pass on requests),\n- a `kind` (the generator implementation to use).\n\nSupported built-in kinds (at time of writing):\n\n- `uuid`\n- `ksuid`\n- `ulid`\n- `xid`\n- `snowflake`\n- `nanoid`\n- `typeid`\n- `pg` (Postgres sequence-backed)\n\nExample:\n\n```/dev/null/generator.yml#L1-21\ngenerator:\n  applications:\n    - name: public-uuid\n      kind: uuid\n    - name: internal-ulid\n      kind: ulid\n    - name: order-seq\n      kind: pg\n```\n\n#### Postgres generator (`kind: pg`)\n\nThe `pg` generator reads the next value from a Postgres sequence using:\n\n- `SELECT nextval($1::regclass)`\n\nThe sequence name is the configured `application.name` (i.e., `Application.Name`).\n\nImportant:\n- The service **does not create sequences**. You must provision them separately (migrations/DB tooling/etc.).\n\n### Mapper configuration\n\nMapper configuration defines a lookup table for identifier translation (useful for legacy migrations):\n\n```/dev/null/mapper.yml#L1-6\nmapper:\n  identifiers:\n    legacy-1: canonical-1\n    legacy-2: canonical-2\n```\n\nSemantics:\n- Mapping is strict: if any input ID is missing from the table, the operation fails.\n- Output order matches input order.\n\n### Health configuration\n\nHealth checks are provided via `go-health` integration. Timing is configured as durations:\n\n```/dev/null/health.yml#L1-6\nhealth:\n  duration: 1s   # how often to run checks\n  timeout:  1s   # max time a single check may take\n```\n\nThe service registers:\n- `noop` and `online` checks always,\n- a `pg` check only if a DB handle is configured/available.\n\n## Running\n\n### Local dev (hot reload)\n\n```/dev/null/commands.sh#L1-3\nmake submodule\nmake dep\nmake dev\n```\n\n`make dev` runs the server using `air` and a config file like:\n\n- `./bezeichner server -i file:test/.config/server.yml`\n\n### Build\n\n```/dev/null/commands.sh#L1-4\nmake build        # builds ./bezeichner (release)\nmake build-test   # builds ./bezeichner test binary (features, race, coverage)\n```\n\n## Usage examples\n\nBelow are examples for both transports. Exact request/response schemas are defined in `api/bezeichner/v1/service.proto`.\n\n### gRPC (grpcurl)\n\nAssuming the service is listening on `localhost:12000` (default in the sample config):\n\nGenerate 3 IDs for application `public-uuid`:\n\n```/dev/null/grpcurl.sh#L1-7\ngrpcurl -plaintext \\\n  -d '{\"application\":\"public-uuid\",\"count\":\"3\"}' \\\n  localhost:12000 \\\n  bezeichner.v1.Service/GenerateIdentifiers\n```\n\nMap identifiers:\n\n```/dev/null/grpcurl.sh#L1-7\ngrpcurl -plaintext \\\n  -d '{\"ids\":[\"legacy-1\",\"legacy-2\"]}' \\\n  localhost:12000 \\\n  bezeichner.v1.Service/MapIdentifiers\n```\n\n### HTTP RPC gateway (curl)\n\nHTTP routes are keyed by the **gRPC full method name**. That means your HTTP client calls the same method identifiers as gRPC.\n\nAssuming the service is listening on `localhost:11000` (default in the sample config):\n\nGenerate identifiers:\n\n```/dev/null/curl.sh#L1-7\ncurl -sS \\\n  -X POST \\\n  -H 'content-type: application/json' \\\n  --data '{\"application\":\"public-uuid\",\"count\":\"3\"}' \\\n  http://localhost:11000/bezeichner.v1.Service/GenerateIdentifiers\n```\n\nMap identifiers:\n\n```/dev/null/curl.sh#L1-7\ncurl -sS \\\n  -X POST \\\n  -H 'content-type: application/json' \\\n  --data '{\"ids\":[\"legacy-1\",\"legacy-2\"]}' \\\n  http://localhost:11000/bezeichner.v1.Service/MapIdentifiers\n```\n\nNote:\n- The exact HTTP path shape is defined by the underlying `go-service` HTTP RPC router; the important part is that routing is done by gRPC full method name.\n\n## Deployment guidance\n\nBezeichner is typically deployed as a shared internal service. Depending on your scale and domain boundaries, you can:\n- run a single global instance,\n- shard by bounded context,\n- run per region/cluster.\n\nIf you use the `pg` generator, ensure database connectivity and sequence provisioning are handled as part of your infrastructure/migrations.\n\n## Design \u0026 dependencies\n\nBezeichner builds on established ID generation libraries:\n- https://github.com/google/uuid\n- https://github.com/segmentio/ksuid\n- https://github.com/oklog/ulid\n- https://github.com/rs/xid\n- https://github.com/sony/sonyflake\n- https://go.jetify.com/typeid\n\nService scaffolding and transport/DI patterns:\n- https://github.com/alexfalkowski/go-service/v2\n\n## Development\n\n### Repository structure\n\nThe project follows:\n- https://github.com/golang-standards/project-layout\n\n### Requirements\n\n- Go (see `go.mod` for version)\n- Ruby (used for end-to-end feature tests; see `.ruby-version`)\n\n### Setup\n\nMost `make` targets come from the `bin/` git submodule:\n\n```/dev/null/setup.sh#L1-3\nmake submodule\nmake dep\nmake setup\n```\n\n### Tests\n\nGo unit/spec tests:\n\n```/dev/null/tests.sh#L1-2\nmake specs\nmake lint\n```\n\nEnd-to-end feature tests:\n\n```/dev/null/tests.sh#L1-1\nmake features\n```\n\n### Changelog\n\nSee `CHANGELOG.md`.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexfalkowski%2Fbezeichner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexfalkowski%2Fbezeichner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexfalkowski%2Fbezeichner/lists"}