{"id":36441132,"url":"https://github.com/kosatnkn/catalyst","last_synced_at":"2026-01-11T21:58:03.608Z","repository":{"id":35967127,"uuid":"166941030","full_name":"kosatnkn/catalyst","owner":"kosatnkn","description":"A Clean Architecture microservice template written in Go.","archived":false,"fork":false,"pushed_at":"2025-12-12T16:30:42.000Z","size":7560,"stargazers_count":15,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-12-14T07:40:25.647Z","etag":null,"topics":["catalyst","clean-architecture","golang","microservices"],"latest_commit_sha":null,"homepage":"","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/kosatnkn.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":null,"dco":null,"cla":null}},"created_at":"2019-01-22T06:37:47.000Z","updated_at":"2025-12-12T16:30:46.000Z","dependencies_parsed_at":"2024-08-10T13:54:36.818Z","dependency_job_id":"77d40317-b060-46ea-a21e-52e73ac822f3","html_url":"https://github.com/kosatnkn/catalyst","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/kosatnkn/catalyst","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosatnkn%2Fcatalyst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosatnkn%2Fcatalyst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosatnkn%2Fcatalyst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosatnkn%2Fcatalyst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kosatnkn","download_url":"https://codeload.github.com/kosatnkn/catalyst/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kosatnkn%2Fcatalyst/sbom","scorecard":{"id":567978,"data":{"date":"2025-08-11","repo":{"name":"github.com/kosatnkn/catalyst","commit":"8fa59259df7052ad5f3d91c112b6dc56ecec02ed"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/26 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:35: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/codeql-analysis.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql-analysis.yml:60: update your workflow using https://app.stepsecurity.io/secureworkflow/kosatnkn/catalyst/codeql-analysis.yml/master?enable=pin","Warn: containerImage not pinned by hash: Dockerfile:2","Warn: containerImage not pinned by hash: Dockerfile:14","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   2 containerImage dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":8,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 2 commits out of 5 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":7,"reason":"3 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2025-3487 / GHSA-hcg3-q754-cr77","Warn: Project is vulnerable to: GO-2025-3503 / GHSA-qxp5-gwg8-xv66","Warn: Project is vulnerable to: GO-2025-3595 / GHSA-vvgc-356p-c3xw"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T15:30:08.799Z","repository_id":35967127,"created_at":"2025-08-20T15:30:08.799Z","updated_at":"2025-08-20T15:30:08.799Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28324629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-11T18:42:50.174Z","status":"ssl_error","status_checked_at":"2026-01-11T18:39:13.842Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["catalyst","clean-architecture","golang","microservices"],"created_at":"2026-01-11T21:58:02.878Z","updated_at":"2026-01-11T21:58:03.601Z","avatar_url":"https://github.com/kosatnkn.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Catalyst\nA `Clean Architecture` microservice template written in `Go`.\n\n![catalyst_logo](./docs/img/catalyst_logo.svg)\n\n[![CI](https://github.com/kosatnkn/catalyst/actions/workflows/ci.yml/badge.svg)](https://github.com/kosatnkn/catalyst/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/kosatnkn/catalyst/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/kosatnkn/catalyst/actions/workflows/codeql-analysis.yml)\n[![Coverage Status](https://coveralls.io/repos/github/kosatnkn/catalyst/badge.svg?branch=master)](https://coveralls.io/github/kosatnkn/catalyst?branch=master)\n![Open Issues](https://img.shields.io/github/issues/kosatnkn/catalyst)\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/kosatnkn/catalyst)\n[![Go Reference](https://pkg.go.dev/badge/github.com/kosatnkn/catalyst/v3.svg)](https://pkg.go.dev/github.com/kosatnkn/catalyst/v3)\n[![Go Report Card](https://goreportcard.com/badge/github.com/kosatnkn/catalyst)](https://goreportcard.com/report/github.com/kosatnkn/catalyst)\n\n## 1. Introduction\nFor **version 3** of **Catalyst**, my main focus was to make it simple, clean and upgradable. Looking back, these are the very things I struggled with in both previous versions. Especially upgradability.\n\nI have removed a substantial amount of code that I had passionately written for **Catalyst** over the years. In hindsight, I realized that I was just reinventing the wheel again and again, while better alternatives already existed. The more code I added for things like dynamic IoC container resolution, generalized DB transactions, and even logging and metric generation, the more opinionated **Catalyst** became.\n\nWith all that bulk gone, **Catalyst** has become more of a template. Now, instead of dictating which resources to use, **Catalyst** simply defines where each type of resource should go. As the developer, you have the freedom to choose whatever you feel best fits your implementation.\n\nFor example, you can use a simple struct implementation as the IoC container and resolve it manually. This is what I’ve done here for demo purposes (and also what I would actually do unless there’s a very good reason to opt for something else). Alternatively, you can plug in a heavy-duty IoC container. The same applies to loggers, database adapters, and so on.\n\nI’m maintaining a separate GitHub repository at [kosatnkn/catalyst-pkgs](https://github.com/kosatnkn/catalyst-pkgs) to host some of the packages I use here. The logger is a wrapper around [rs/zerolog](https://github.com/rs/zerolog), and the configuration parser is a wrapper around [spf13/viper](https://github.com/spf13/viper). Feel free to swap them out for whatever better suits your needs.\n\n## 2. Architecture\nThere are many ways to organize a project that follows the **Clean Architecture** paradigm. This is how I’ve organized **Catalyst**.\n\n![Clean Architecture](./docs/img/clean_arch.drawio.svg)\n\nWhen this architecture is mapped to the directory structure of **Catalyst**, it looks like this.\n\n![Clean Architecture Dir Mapping](./docs/img/clean_arch_dir_mapping.drawio.svg)\n\n### 2.1. Domain\nThe **Domain** contains all the business logic executed by the microservice. It consists of three main parts: **Entities**, **Use Cases**, and **Boundary**.\n\n#### 2.1.1. Entities\n**Entities** define the data model for the domain. These are simple `Go` structs used within the domain as well as across the domain boundary to transfer data.\n\n#### 2.1.2. Usecases\n**Usecases** contain all the business logic. Any external dependencies needed by the Use Cases (e.g., database resources) are injected into them using dependency inversion.\n\n#### 2.1.3. Boundary\nThe **Boundary** marks the interface between the **Domain** and the **orchestration layers**. It contains contracts (`Go` interfaces) that facilitate dependency inversion.\n\n### 2.2. Orchestration\nOrchestration contains **Infrastructure**, **Presentation** and **Persistence**.\n\n#### 2.2.1. Infrastructure\n**Infrastructure** contains the lowest-level resources needed by the microservice, such as configuration and the IoC container.\n\n#### 2.2.2. Presentation\n**Presentation** contains all outward-facing interfaces. These are the communication channels between the microservice and the outside world. This is where you place your RESTful, GraphQL, gRPC, or WebSocket servers. It’s worth noting that you don’t need to implement all of these in a single microservice; it solely depends on the specifics of your implementation.\n\nTelemetry configurations for metrics and traces can be set up here as well. However, with currently available options, I would use an [eBPF](https://ebpf.io/) collector to gather telemetry. Unless you need to export custom metrics from your service, this approach provides sufficient information about your service.\n\n#### 2.2.3. Persistence\n**Persistence** is used to hold all data-related resources, whether it’s simple file writes, an RDBMS, an object store, or even an event-sourcing system backed by a local store. The important thing to remember is that all implementation details should be encapsulated within the **Persistence** layer. The **Domain** using these resources must not know (or care) about how persistence is implemented. Saving to a static file should be no different than saving to a messaging backend from the perspective of the **Domain** layer. All complexities related to the underlying persistence technologies should remain contained within the **Persistence** layer.\n\n## 3. Usage\n### 3.1. Create New\n**Catalyst** comes with a script that makes it easy to create new projects from it. You can find this script included with each release. It is version-locked to that specific release.\n\nUse the following command to directly create a new microservice using **Catalyst** in your current working directory.\n```shell\ncurl -fsSL https://github.com/kosatnkn/catalyst/releases/download/v3.2.0/new_from_v3.2.0.sh | bash -s -- --module=\"example.com/dummyuser/sampler\" --yes\n```\n\nIf you prefer to first download the script, inspect it, and then run it (which is the safer approach), use following commands.\n```shell\n# download first\ncurl -fsSL -o new_from_v3.2.0.sh https://github.com/kosatnkn/catalyst/releases/download/v3.2.0/new_from_v3.2.0.sh\n\n# inspect\n# ...\n\n# once ready, run\nchmod +x new_from_v3.2.0.sh\n./new_from_v3.2.0.sh --module=\"example.com/dummyuser/sampler\"\n```\n\n\u003e **NOTE:**\n\u003e\n\u003eThe directory name for your new microservice will be inferred from the Go module name that you provide with the `--module` parameter.\n\u003e\n\u003e The script can handle version information in the module name when inferring the directory name. For example, both `example.com/dummyuser/sampler` and `example.com/dummyuser/sampler/v2` will produce `sampler` as the directory name.\n\n### 3.2. Understanding How it Works\nThe best place to start how a microservice based on Catalyst works is the `main.go` file and the `main` function.\n\nYou can easily identify how the microservice starts up and shuts down by going through the `main` function in execution order.\n\nBy default it will,\n- Parse all configurations in to the `infra.Config` struct.\n- Resolve the container.\n- Start the **Presentation** layer. This includes the `REST` server, a `WebSocket` server etc.\n- Block the `main` function using a channel that waits for interrupt signals.\n\n### 3.3. Configuration\nYou can provide configurations in one of two ways. Using a `config.yaml` file or using environment variables.\n\n#### 3.2.1. Configure Using `config.yaml`\nYou can start by using the `config.yaml.example` file to create the basic `config.yaml` file. The current setup expects the config file (if there is a one) to be named as `config.yaml`.\n\nThe structure of the `config.yaml` file depends on the structure of the `Config` struct in `./infra/config.go` file.\n\n#### 3.2.2. Configure Using Environment Variables\n\u003e NOTE: When using environment variables it will override values read from the `config.yaml` file.\n\nTo avoid conflicts environment variables used are prefixed. The prefix to use is configurable (see `config.Settings` used in the `main` function in `main.go`).\n\nNames of environment variables too depends on the structure of the `Config` struct in `./infra/config.go` file. You can find an example usage in the `Makefile`s `run-with-env` section.\n\n### 3.3. Metadata\nBasic set of metadata such as build info for the microservice can be obtained using the `metadata` package that comes with the microservice.\n\nYou will have to use `make build` or `make run` commands from the `Makefile` to have these metadata properly read and loaded.\n\nIf you need to add some additional static metadata, you can put them in the `./metadata.txt` file.\n\n### 3.4. Makefile\nA `Makefile` is used to streamline `run`, `build`, `test` and `dependency update` workflows.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkosatnkn%2Fcatalyst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkosatnkn%2Fcatalyst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkosatnkn%2Fcatalyst/lists"}