From 8ff7b0f150ead0ed7ca153e24207e275b4f9b10d Mon Sep 17 00:00:00 2001 From: Anar Alishov Date: Sat, 22 Nov 2025 22:04:41 +0100 Subject: [PATCH 1/2] Initialize project with core library, tests, workflows, templates, and documentation. Signed-off-by: Anar Alishov --- .github/ISSUE_TEMPLATE/bug_report.yml | 59 +++++++++++ .github/ISSUE_TEMPLATE/feature_request.yml | 30 ++++++ .github/PULL_REQUEST_TEMPLATE.md | 14 +++ .github/dependabot.yml | 16 +++ .github/workflows/ci.yml | 42 ++++++++ .gitignore | 30 ++++++ CHANGELOG.md | 23 +++++ CODE_OF_CONDUCT.md | 33 +++++++ CONTRIBUTING.md | 35 +++++++ LICENSE | 2 +- README.md | 55 +++++++++++ SECURITY.md | 8 ++ TRADEMARK.md | 12 +++ go.mod | 5 + go.sum | 2 + id.go | 51 ++++++++++ test/id_test.go | 110 +++++++++++++++++++++ 17 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 CHANGELOG.md create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 README.md create mode 100644 SECURITY.md create mode 100644 TRADEMARK.md create mode 100644 go.mod create mode 100644 go.sum create mode 100644 id.go create mode 100644 test/id_test.go diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..258c9cf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,59 @@ +name: Bug report +description: Create a report to help us improve +labels: [bug] +title: "bug: " +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: input + id: version + attributes: + label: Version + description: Output of `go version` and the library version (commit/semver) + placeholder: e.g. go1.22.3 / v1.0.0 + - type: textarea + id: description + attributes: + label: Description + description: A clear and concise description of what the bug is. + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: Please provide minimal reproducible example. + placeholder: | + 1. Go code snippet + 2. Commands you ran + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + - type: textarea + id: actual + attributes: + label: Actual behavior + validations: + required: true + - type: dropdown + id: os + attributes: + label: Operating system + options: + - macOS + - Linux + - Windows + - Other + - type: textarea + id: logs + attributes: + label: Logs + description: Paste any relevant logs or stack traces. + render: shell diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..139ba52 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,30 @@ +name: Feature request +description: Suggest an idea for this project +labels: [enhancement] +title: "feat: " +body: + - type: markdown + attributes: + value: | + Thanks for your suggestion! Please fill in the details below. + - type: input + id: context + attributes: + label: Context + description: What problem are you trying to solve? + placeholder: Brief background + - type: textarea + id: proposal + attributes: + label: Proposal + description: Describe the solution you'd like. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + - type: textarea + id: additional + attributes: + label: Additional context diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..181fdb1 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,14 @@ +## Summary +Please provide a short summary of the changes. + +## Motivation +Why is this change needed? Link related issues (e.g., closes #123). + +## Changes +- + +## Checklist +- [ ] Tests added/updated (if applicable) +- [ ] `go test ./...` passes locally +- [ ] Documentation updated (README/CHANGELOG if needed) +- [ ] I agree that my contributions are licensed under the repository license diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..6a53a2e --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + commit-message: + prefix: "chore(deps)" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + commit-message: + prefix: "chore(actions)" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..d471f02 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,42 @@ +name: CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + go-version: [ '1.21.x', '1.22.x', 'stable' ] + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: ${{ matrix.go-version }} + + - name: Cache Go modules + uses: actions/cache@v4 + with: + path: | + ~/.cache/go-build + ~/go/pkg/mod + key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go-${{ matrix.go-version }}- + ${{ runner.os }}-go- + + - name: Verify + run: | + go version + go vet ./... + + - name: Test + run: | + go test ./... -v diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..18127e1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out +coverage* + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# IDE/editor files +.idea/ +.vscode/ +*.iml + +# OS files +.DS_Store +Thumbs.db + +# Temporary files +*.tmp +*.swp +vendor/ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4627832 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [0.1.0] – 2025-11-21 + +### Added + +Provides a simple thread-safe dependency injection container with singleton and factory registries, parameter storage, and introspection helpers. + +Features include: +- Initial release of the github.com/kuetix/container package. +- Thread-safe singleton registry (ToFetch, ToFetchFunc, Fetch). +- Thread-safe factory registry with on-demand resolution (ToResolve, Resolve). +- Unified lookup via Get, resolving either singleton or factory. +- Parameters store (ToParameter, Parameter) for lightweight config values. +- Introspection helpers: +- Has, CanFetch, CanResolve, HasParameter. +- Reset() helper for testing. +- Project documentation: README.md, LICENSE, TRADEMARK.md. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..483974f --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,33 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. + +## Our Standards +Examples of behavior that contributes to a positive environment include: +- Demonstrating empathy and kindness +- Being respectful of differing opinions +- Gracefully accepting constructive criticism + +Unacceptable behavior includes: +- Harassment, trolling, or insults +- Publishing others’ private information + +## Enforcement Responsibilities +Project maintainers are responsible for clarifying and enforcing our standards. + +## Scope +This Code applies within all community spaces and when an individual is officially representing the project. + +## Enforcement +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the maintainers at security@kuetix.com. All complaints will be reviewed and investigated promptly and fairly. + +## Enforcement Guidelines +Maintainers will follow these Community Impact Guidelines: +1. Correction +2. Warning +3. Temporary Ban +4. Permanent Ban + +## Attribution +This Code of Conduct is adapted from the Contributor Covenant, version 2.1, available at https://www.contributor-covenant.org/version/2/1/code_of_conduct.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ca1fd24 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# Contributing to kuetix/uuid + +Thank you for considering a contribution! This project follows a lightweight workflow to keep things simple and friendly. + +## Getting started +- Go 1.21+ is recommended. The module should work with the version declared in `go.mod`. +- Clone the repo and run tests: + ```bash + go test ./... + ``` + +## Development workflow +1. Fork the repository and create your branch from `main`. +2. Write clear, minimal changes focused on a single topic. +3. Add or update tests where applicable: place tests under `test/`. +4. Ensure `go fmt`/`go vet` look good and tests pass locally. +5. Open a pull request with a succinct title and description of the change and motivation. + +## Commit messages +- Use conventional, descriptive messages (e.g., `fix:`, `feat:`, `docs:`). +- Keep the first line short; add context in the body when needed. + +## Code style +- Match the existing code style. +- Keep public API surface minimal and well-documented. + +## Reporting issues +- Search existing issues first. +- Include Go version, OS, steps to reproduce, expected/actual behavior. + +## Security +Please do NOT open public issues for security reports. See `SECURITY.md` for the private reporting process. + +## License +By contributing, you agree that your contributions are licensed under the MIT License of this repository. diff --git a/LICENSE b/LICENSE index 7b43037..04b79f9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 kuetix +Copyright (c) 2025 Anar Alishov (Kuetix™) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md new file mode 100644 index 0000000..36bab04 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# kuetix/uuid + +Small utilities around UUID generation and formatting built on top of `github.com/google/uuid`. + +[![CI](https://github.com/kuetix/uuid/actions/workflows/ci.yml/badge.svg)](https://github.com/kuetix/uuid/actions/workflows/ci.yml) +[![Go Reference](https://pkg.go.dev/badge/github.com/kuetix/uuid.svg)](https://pkg.go.dev/github.com/kuetix/uuid) +[![Go Report Card](https://goreportcard.com/badge/github.com/kuetix/uuid)](https://goreportcard.com/report/github.com/kuetix/uuid) + +## Install +``` +go get github.com/kuetix/uuid +``` + +## Usage +```go +package main + +import ( + "fmt" + kuuid "github.com/kuetix/uuid" +) + +func main() { + // Deterministic UUIDv5 derived from an identity string + u := kuuid.IdV5("example") + fmt.Println("uuid:", u.String()) // canonical XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + + // Canonical string form + fmt.Println("UUId:", kuuid.UUId("example")) + + // Dashless hex (32 chars) + fmt.Println("Id:", kuuid.Id("example")) + + // Base64 encoding of the 16-byte UUID + fmt.Println("Base64:", kuuid.Base64Id("example")) + + // Remove dashes from a canonical UUID string + fmt.Println("UId:", kuuid.UId(u.String())) +} +``` + +## Development +- Minimal Go module with tests under `test/`. +- Run all tests: +``` +go test ./... +``` + +See `CONTRIBUTING.md` for details. + +## License +MIT License — see the `LICENSE` file for details. + +Kuetix™ is an unregistered trademark of Anar Alishov. All rights reserved. +The Kuetix™ name and logo are not covered by this license. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..17bc327 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,8 @@ +# Security Policy + +If you discover a security vulnerability, please report it privately. + +- Contact: support@kuetix.com +- Please include: description, steps to reproduce (if possible), impact, affected versions, and any suggested mitigation. + +Do not create a public issue for security reports. diff --git a/TRADEMARK.md b/TRADEMARK.md new file mode 100644 index 0000000..2e8e339 --- /dev/null +++ b/TRADEMARK.md @@ -0,0 +1,12 @@ +# Kuetix™ Trademark Notice + +Kuetix™ is an unregistered trademark of Anar Alishov. + +You may use the Kuetix name to refer to the open source project, the Workflow Orchestrator Engine (WOE), the Workflow Specific Language (WSL), and the Kuetix ecosystem, as long as such use: +- does not imply endorsement or affiliation, +- does not cause confusion, +- and follows fair use principles. + +Unauthorized commercial use of the Kuetix name is prohibited. + +© 2025 Anar Alishov. All rights reserved. diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4b6420d --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/kuetix/uuid + +go 1.25.1 + +require github.com/google/uuid v1.6.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..7790d7c --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= diff --git a/id.go b/id.go new file mode 100644 index 0000000..0dca41a --- /dev/null +++ b/id.go @@ -0,0 +1,51 @@ +package uuid + +import ( + "crypto/sha256" + "encoding/base64" + "strings" + + "github.com/google/uuid" +) + +func IdV5(identity string) uuid.UUID { + namespace := uuid.NameSpaceOID + hashId := sha256.Sum256([]byte(identity)) + uuidV5 := uuid.NewHash(sha256.New(), namespace, hashId[:], 5) + + return uuidV5 +} + +//goland:noinspection GoUnusedExportedFunction +func Base64Id(identity string) string { + binary, _ := IdV5(identity).MarshalBinary() + return base64.StdEncoding.EncodeToString(binary) +} + +func UUId(identity string) string { + return IdV5(identity).String() +} + +func Id(identity string) string { + return UId(UUId(identity)) +} + +func UId(id string) string { + ui := uuid.MustParse(id) + return strings.ReplaceAll(ui.String(), "-", "") +} + +//goland:noinspection GoUnusedExportedFunction +func Parsed(uid string) string { + uuidV5, _ := uuid.Parse(uid) + + return uuidV5.String() +} + +//goland:noinspection GoUnusedExportedFunction +func UUIDToInt(u uuid.UUID) []byte { + // Convert UUID to bytes + uuidBytes := u[:] + + return uuidBytes +} diff --git a/test/id_test.go b/test/id_test.go new file mode 100644 index 0000000..7bd2476 --- /dev/null +++ b/test/id_test.go @@ -0,0 +1,110 @@ +package uuid_test + +import ( + "encoding/base64" + "encoding/hex" + "strings" + "testing" + + kuuid "github.com/kuetix/uuid" +) + +func TestIdV5_DeterministicAndDistinct(t *testing.T) { + id1 := kuuid.IdV5("test") + id2 := kuuid.IdV5("test") + if id1 != id2 { + t.Fatalf("IdV5 should be deterministic: %s vs %s", id1, id2) + } + + idA := kuuid.IdV5("A") + idB := kuuid.IdV5("B") + if idA == idB { + t.Fatalf("IdV5 should differ for different identities: %s vs %s", idA, idB) + } + + // Version should be 5 + if v := id1.Version(); v != 5 { + t.Fatalf("expected version 5, got %d", v) + } +} + +func TestBase64Id_RoundTrip(t *testing.T) { + b64 := kuuid.Base64Id("test") + raw, err := base64.StdEncoding.DecodeString(b64) + if err != nil { + t.Fatalf("invalid base64 produced: %v", err) + } + if len(raw) != 16 { + t.Fatalf("uuid binary should be 16 bytes, got %d", len(raw)) + } +} + +func TestUUId_Format(t *testing.T) { + s := kuuid.UUId("test") + if len(s) != 36 { + t.Fatalf("expected canonical uuid string of length 36, got %d (%s)", len(s), s) + } + if strings.Count(s, "-") != 4 { + t.Fatalf("expected 4 dashes in canonical uuid string: %s", s) + } +} + +func TestId_FormatAndConsistency(t *testing.T) { + // Id returns a 32-char hex string without dashes + s := kuuid.Id("test") + if len(s) != 32 { + t.Fatalf("expected 32-char hex string without dashes, got %d (%s)", len(s), s) + } + if _, err := hex.DecodeString(s); err != nil { + t.Fatalf("Id should be hex-only: %v", err) + } + + // Consistency: Id(identity) == UId(UUId(identity)) + s2 := kuuid.UId(kuuid.UUId("test")) + if s != s2 { + t.Fatalf("Id should equal UId(UUId(identity)): %s vs %s", s, s2) + } +} + +func TestUId_RemovesDashes(t *testing.T) { + canonical := kuuid.UUId("test") + noDash := kuuid.UId(canonical) + if strings.Contains(noDash, "-") { + t.Fatalf("UId should remove dashes: %s", noDash) + } + if len(noDash) != 32 { + t.Fatalf("UId should return 32-char hex without dashes, got %d (%s)", len(noDash), noDash) + } +} + +func TestParsed_Normalizes(t *testing.T) { + canonical := kuuid.UUId("test") + upper := strings.ToUpper(canonical) + normalized := kuuid.Parsed(upper) + if normalized != canonical { + t.Fatalf("Parsed should return canonical-lowercase form: %s vs %s", normalized, canonical) + } +} + +func TestUUIDToInt_BytesMatchMarshalBinary(t *testing.T) { + u := kuuid.IdV5("test") + b1 := kuuid.UUIDToInt(u) + b2, err := u.MarshalBinary() + if err != nil { + t.Fatalf("MarshalBinary error: %v", err) + } + if len(b1) != 16 || len(b2) != 16 { + t.Fatalf("uuid bytes must be 16; got %d and %d", len(b1), len(b2)) + } + for i := range b1 { + if b1[i] != b2[i] { + t.Fatalf("byte mismatch at %d: %d vs %d", i, b1[i], b2[i]) + } + } +} + +func BenchmarkIdV5(b *testing.B) { + for i := 0; i < b.N; i++ { + _ = kuuid.IdV5("test") + } +} From ff8ced9ae68a34517e68aaacc3d523bd6f916324 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:05:23 +0000 Subject: [PATCH 2/2] chore(actions): bump actions/checkout from 4 to 6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d471f02..87bf977 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: go-version: [ '1.21.x', '1.22.x', 'stable' ] steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Go uses: actions/setup-go@v5