Help us shape the future of Go! Take the 2026 Go Developer Survey

skills

package
v0.1.310 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 1, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package skills holds shared, dependency-light helpers for the Chainguard skills harden API that both the mono server and the chainctl client link — chiefly HardenJobID, the deterministic harden job id. See HardenJobID for how the id is computed and why the two callers must hash identically.

Index

Examples

Constants

View Source
const GateRejectedMessage = "post-evaluation gate rejected hardened skill"

GateRejectedMessage is the Operation.error message a harden operation carries when the post-evaluation gate rejects the hardened skill. It is deliberately distinct from the generic hardening failure so a client can tell a verdict ("the gate looked at this and said no") from an outage ("we never got a verdict"), and retry only the latter. Both the service that produces it and the variance measurement that classifies it read this constant, so the two cannot drift apart silently.

View Source
const HardenNamePrefix = "harden/"

HardenNamePrefix is the prefix of every harden operation name. The operation name is the job id, namespaced under the target group: "harden/{group-uidp}/{jobhash}".

Variables

This section is empty.

Functions

func GroupFromHardenName

func GroupFromHardenName(name string) (string, error)

GroupFromHardenName extracts the group UIDP embedded in a harden operation name. The name is "harden/{group}/{jobhash}"; the group UIDP may itself contain "/" (hierarchical UIDPs), so the job hash is the final path segment and the group is everything before it. It is the inverse of HardenOperationName and the boundary the api-impl cross-tenant read check uses to confirm a caller's group owns an operation.

Example
package main

import (
	"fmt"

	"chainguard.dev/sdk/skills"
)

func main() {
	name := skills.HardenOperationName("org1/child", "user1", "pdf", "sha256:abc")
	group, err := skills.GroupFromHardenName(name)
	fmt.Println(err)
	fmt.Println(group)
}
Output:
<nil>
org1/child

func HardenJobID

func HardenJobID(orgID, userID, skillName, contentDigest string) string

HardenJobID computes the deterministic harden job id from its four content dimensions. It is content-addressed, so identical inputs always yield the same id — the property the operation store relies on for idempotent submit (a re-submit of the same skill into the same group by the same user is a no-op).

  • orgID: the target group UIDP (authorized against the caller).
  • userID: the submitting user's identity subject, so each user gets their own tracked job.
  • skillName: the skill's catalog name.
  • contentDigest: the sha256 digest of the uploaded uploads.cgr.dev artifact.

Two users hardening the same bundle run separate jobs AND land separate outputs: each user's hardened artifact is published under a per-user path, skills.cgr.dev/<group>/<user>/<skill_name>@sha256:<hardened-digest>, so the two never overwrite or race the same digest. The user-less skills.cgr.dev/<group>/<skill_name> path is reserved for promotion (blessing a hardened skill to the org level). userID being a dimension of both this id and the output path is what keeps that per-user isolation intact.

The returned value is a hex sha256 over a version tag and the four fields, each length-prefixed so no field boundary is ambiguous (e.g. so a userID ending in the skillName's prefix cannot alias a different split).

IMPORTANT: this MUST hash identically to the chainctl client's local recomputation and to skillchain2's job key. Any change here is a coordinated cross-repo change; bump hardenJobIDVersion rather than silently altering the input encoding.

Example
package main

import (
	"fmt"

	"chainguard.dev/sdk/skills"
)

func main() {
	// The same inputs always yield the same id (idempotent submit / dedupe).
	a := skills.HardenJobID("org1", "user1", "pdf", "sha256:abc")
	b := skills.HardenJobID("org1", "user1", "pdf", "sha256:abc")
	fmt.Println(a == b)
	// A different content digest yields a different id.
	c := skills.HardenJobID("org1", "user1", "pdf", "sha256:def")
	fmt.Println(a == c)
}
Output:
true
false

func HardenOperationName

func HardenOperationName(orgID, userID, skillName, contentDigest string) string

HardenOperationName returns the full operation name for a harden job: the job id namespaced under the target group. Both the store record and the id handed to skillchain2 use this name.

Example
package main

import (
	"fmt"
	"strings"

	"chainguard.dev/sdk/skills"
)

func main() {
	name := skills.HardenOperationName("org1/child", "user1", "pdf", "sha256:abc")
	fmt.Println(strings.HasPrefix(name, "harden/org1/child/"))
}
Output:
true

func HardenRetryOperationName added in v0.1.293

func HardenRetryOperationName(failedOperation string) (string, error)

HardenRetryOperationName derives the next attempt from a failed operation's full name. Transport retries therefore return the same attempt; a further retry must name the newly failed operation. The caller verifies ownership and failure before creating it.

Example
package main

import (
	"fmt"

	"chainguard.dev/sdk/skills"
)

func main() {
	failed := skills.HardenOperationName("org/child", "user", "pdf", "sha256:abc")
	retry, err := skills.HardenRetryOperationName(failed)
	if err != nil {
		fmt.Println(err)
		return
	}
	repeated, err := skills.HardenRetryOperationName(failed)
	if err != nil {
		fmt.Println(err)
		return
	}
	group, err := skills.GroupFromHardenName(retry)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(group, retry != failed, retry == repeated)
}
Output:
org/child true true

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL