Skip to content

Repository files navigation

kiit-codes

A Kotlin library for classifying and handling success and failure.

A small, dependency-free status and error taxonomy for application outcomes, with extensible codes, protocol mappings, validation, typed exceptions, and optional Result<T, E> integration.

Maven Central Build License Kotlin

Part of Kiit Β· Docs Β· Blog

Kiit Codes overview

πŸ“š Table of Contents

# Topic Description
1 πŸ’‘ Why Problems Codes is designed to solve
2 πŸš€ Start Installation and a quick example
3 πŸ—‚οΈ Taxonomy The Status β†’ Group β†’ Code model
4 🧩 Extensibility Built-in and custom domain codes
5 πŸ”€ Protocols HTTP, gRPC, and custom protocol mappings
6 βš™οΈ Usage Status, validation, exceptions, and Result
7 πŸ—ΊοΈ Roadmap Planned improvements and future work
8 πŸ“– Learn More Deeper documentation and design topics
9 πŸ“‹ Requirements Platforms and dependencies
10 🀝 Contributing Build, test, and contribute
11 πŸ“„ License Apache 2.0 license

Why

Applications need to communicate a simple idea consistently: what happened?

In practice, success and failure are often modeled differently across domains, application layers, protocols, and error-handling approaches. This creates several recurring problems:

# Problem Description
1 Classification No shared taxonomy for modeling success and failure.
2 Consistency Outcomes vary across application layers and protocols.
3 Fragmentation Validation, exceptions, statuses, and results use different approaches.
4 Boilerplate Similar error types and handling are rebuilt across projects and teams.
5 Specificity Generic errors often lack precise domain meaning.

kiit-codes provides a shared application-level model for these concerns.

A fixed taxonomy provides consistent classification, extensible codes preserve domain-specific meaning, and protocol mappings keep application outcomes independent from their transport. The same model can then be used across statuses, validation, exceptions, and result types.

Start

Gradle (Kotlin DSL):

dependencies {
    implementation("dev.kiit:kiit-codes:1.0.1")
}

A status can represent an outcome without requiring exceptions or a result type:

import kiit.codes.*

fun authorize(userId: String, requesterId: String): Status =
    if (userId != requesterId) Restricted.UNAUTHORIZED
    else Succeeded.SUCCESS

when (val status = authorize(userId, requesterId)) {
    is Passed -> log.info("ok: ${status.name}")
    is Failed -> log.warn("failed: ${status.name} β€” ${status.message}")
}

Built-in codes expose stable fields suitable for application logic, logging, APIs, and diagnostics:

{
    "name"    : "CONFLICT",
    "group"   : "Rejected",
    "origin"  : "kiit",
    "success" : false,
    "message" : "The request conflicts with the current state"
}

Taxonomy

Codes uses a three-tier model:

Tier Name Fixed/Open Suggested wording
Tier 1 Status Fixed Classifies an outcome as Passed or Failed.
Tier 2 Group Fixed Classifies the kind of success or failure.
Tier 3 Code Open Identifies a specific outcome using built-in or domain-specific codes.

Status β†’ Group β†’ Code

Status and Group are fixed so applications share the same high-level meaning. Code is open: Kiit supplies common defaults while applications can add their own domain-specific codes.

Kiit Codes taxonomy

The two statuses are:

  • Passed β€” Succeeded, Pending, Excluded, Information
  • Failed β€” Restricted, Invalid, Rejected, Unserved

Each code provides an id, name, group, origin, message, and success flag. Built-in codes use the kiit origin and each group has a default code for cases where more precision is unnecessary.

The built-in taxonomy contains common application outcomes such as SUCCESS, CREATED, DENIED, INVALID_VALUE, CONFLICT, TIMEOUT, and UNEXPECTED.

Extensibility

The taxonomy stays consistent while codes remain open to your domain.

Kiit Codes custom codes

Custom codes use the same group types as Kiit's defaults:

import kiit.codes.Failed

// Example custom code
val PAYMENT_DECLINED = Failed.Rejected(
    name = "PAYMENT_DECLINED",
    message = "Payment declined",
    origin = "payments"
)

PAYMENT_DECLINED remains a Rejected outcome everywhere in the system while retaining its domain-specific identity. The origin keeps custom namespaces distinct from Kiit and from other modules or teams.

Protocols

Application outcomes should describe what happened, independently of how they are transported.

Kiit codes can be mapped to protocol-specific representations at system boundaries.

Kiit Codes protocol mappings

HTTP

CodesToHttp maps statuses to HTTP codes using group defaults plus specific overrides where needed.

import kiit.codes.*

val http = CodesToHttp()

http.toCode(Succeeded.CREATED) // 201
http.toCode(Invalid.INVALID_VALUE) // 400
http.toStatus(404)?.name // "NOT_FOUND"

Reverse conversion is deterministic but can be lossy because multiple application codes may map to the same HTTP status.

gRPC

CodesToGrpc follows the same model and covers all gRPC status codes.

import kiit.codes.*

val grpc = CodesToGrpc()

grpc.toCode(Restricted.DENIED)   // 7, PERMISSION_DENIED
grpc.toStatus(6)?.name           // "CONFLICT", ALREADY_EXISTS reversed

The mapping abstraction is not limited to HTTP and gRPC. CodeLookup and CompositeLookup can be used to define or extend mappings for other protocols.

val lookup = CompositeLookup(
    base = CodesToHttp(),
    extensions = mapOf(PAYMENT_DECLINED to 402)
)

lookup.toCode(PAYMENT_DECLINED) // 402

Usage

Codes is designed to work at different application boundaries without requiring one error-handling style.

Status

Use Status when the outcome itself is enough.

import kiit.codes.*

fun authorize(userId: String, requesterId: String): Status =
    if (userId != requesterId) Restricted.UNAUTHORIZED
    else Succeeded.SUCCESS

when (val status = authorize(userId, requesterId)) {
    is Passed -> log.info("ok: ${status.name}")
    is Failed -> log.warn("failed: ${status.name} β€” ${status.message}")
}

Kiit Codes usage

Roadmap

kiit-codes has been extracted from kiit framework and polished as a standalone module. This has been used in production for over 4+ years to power mobile and server kotlin applications. Current work is focused on the Kotlin release, documentation, examples, and ecosystem integration.

# Topic Description
1 Documentation Update documentation and examples as needed.
2 TypeScript Add native TypeScript support with an idiomatic implementation of the same Codes taxonomy and semantics.
3 Taxonomy Continue taxonomy review based on real-world usage and community feedback.

See GitHub Issues for current work and discussions.

Learn More

# Topic Description
1 Taxonomy Explore every built-in group and code, their intended meanings, defaults, and distinctions. Read the taxonomy docs.
2 Extensibility Learn how extensibility works and how to create domain-specific codes while keeping the shared taxonomy intact. Read the extensibility docs.
3 Protocols See the complete HTTP and gRPC mappings and learn how to create custom mappings. Read the protocol docs.
4 Validation Learn how Err, Checked, and collect model validation and accumulate multiple errors. Read the validation docs.
5 Exceptions See the typed exception hierarchy and patterns for integrating Codes with exception-based boundaries. Read the exception docs.
6 Result Learn how the separate kiit-result module builds Result<T, E> handling on top of the same Codes taxonomy. Read the Result docs.
7 FAQ Answers to common questions about the taxonomy, design choices, alternatives, adoption, AI considerations, and project maturity. Read the FAQ.
8 Design Read more about the reasoning behind fixed groups, extensible codes, protocol independence, and where Codes fits relative to domain errors. Read the design docs.

Requirements

  • Kotlin Multiplatform
  • JVM, Android, iOS (simulator, iosArm64, x64)
  • No external runtime dependencies

Contributing

Contributions and design feedback are welcome. See BUILD.md for build, test, and publish instructions.

License

Apache License 2.0


kiit-codes is one module of Kiit β€” a lightweight, modular Kotlin framework for building server applications, APIs, CLIs, and jobs.

Adopt one module at a time.

About

A library to classify and handle success and failure at any layer of an app. Compatible with all gRPC and most common HTTP status codes. Usable as a plain status, validation or structured exceptions.

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages