Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29815c49b8 |
@@ -0,0 +1,7 @@
|
||||
package configuration
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
// SemanticReference is a typed cross-owner reference; settings remain
|
||||
// Configuration-owned records.
|
||||
type SemanticReference = ids.SemanticRef
|
||||
@@ -0,0 +1,7 @@
|
||||
package epistemics
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
// SemanticReference identifies evidence-related records without transferring
|
||||
// canonical ownership to Epistemics.
|
||||
type SemanticReference = ids.SemanticRef
|
||||
@@ -0,0 +1,7 @@
|
||||
package self
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
// SemanticReference lets SELF cite evidence and capabilities without owning
|
||||
// their canonical state.
|
||||
type SemanticReference = ids.SemanticRef
|
||||
@@ -0,0 +1,7 @@
|
||||
package situation
|
||||
|
||||
import "git.cin.su/m/Assistant/platform/ids"
|
||||
|
||||
// SemanticReference keeps Situation references transport-neutral while
|
||||
// ContextScope semantics remain owned by Situation.
|
||||
type SemanticReference = ids.SemanticRef
|
||||
@@ -0,0 +1,97 @@
|
||||
package world
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"git.cin.su/m/Assistant/platform/ids"
|
||||
)
|
||||
|
||||
// SemanticReference is the transport envelope used by World contracts. It is
|
||||
// a reference only; it does not expose another owner's storage.
|
||||
type SemanticReference = ids.SemanticRef
|
||||
|
||||
type PrincipalRealm string
|
||||
|
||||
const (
|
||||
RealmPersonal PrincipalRealm = "PERSONAL"
|
||||
RealmShared PrincipalRealm = "SHARED"
|
||||
RealmPublic PrincipalRealm = "PUBLIC"
|
||||
RealmSystem PrincipalRealm = "SYSTEM"
|
||||
)
|
||||
|
||||
type SensitivityClass string
|
||||
|
||||
const (
|
||||
SensitivityPublic SensitivityClass = "PUBLIC"
|
||||
SensitivityPrivate SensitivityClass = "PRIVATE"
|
||||
SensitivityRestricted SensitivityClass = "RESTRICTED"
|
||||
SensitivitySecretReference SensitivityClass = "SECRET_REFERENCE"
|
||||
)
|
||||
|
||||
type ValueTypeKind string
|
||||
|
||||
const (
|
||||
ValueString ValueTypeKind = "STRING"
|
||||
ValueInteger ValueTypeKind = "INTEGER"
|
||||
ValueDecimal ValueTypeKind = "DECIMAL"
|
||||
ValueBoolean ValueTypeKind = "BOOLEAN"
|
||||
ValueTime ValueTypeKind = "TIME"
|
||||
ValueDuration ValueTypeKind = "DURATION"
|
||||
ValueEnum ValueTypeKind = "ENUM"
|
||||
ValueReference ValueTypeKind = "REFERENCE"
|
||||
ValueBinaryRef ValueTypeKind = "BINARY_REF"
|
||||
ValueList ValueTypeKind = "LIST"
|
||||
ValueStruct ValueTypeKind = "STRUCT"
|
||||
)
|
||||
|
||||
type ValueField struct {
|
||||
Name string
|
||||
Type ValueTypeSpec
|
||||
}
|
||||
|
||||
type ValueTypeSpec struct {
|
||||
Kind ValueTypeKind
|
||||
Element *ValueTypeSpec
|
||||
Fields []ValueField
|
||||
EnumValues []string
|
||||
ReferenceKind string
|
||||
}
|
||||
|
||||
func (s ValueTypeSpec) Validate() error {
|
||||
if s.Kind == "" {
|
||||
return fmt.Errorf("value type kind is required")
|
||||
}
|
||||
switch s.Kind {
|
||||
case ValueList:
|
||||
if s.Element == nil {
|
||||
return fmt.Errorf("list element type is required")
|
||||
}
|
||||
return s.Element.Validate()
|
||||
case ValueStruct:
|
||||
if len(s.Fields) == 0 {
|
||||
return fmt.Errorf("struct fields are required")
|
||||
}
|
||||
seen := map[string]struct{}{}
|
||||
for _, field := range s.Fields {
|
||||
if field.Name == "" {
|
||||
return fmt.Errorf("struct field name is required")
|
||||
}
|
||||
if _, ok := seen[field.Name]; ok {
|
||||
return fmt.Errorf("duplicate struct field %q", field.Name)
|
||||
}
|
||||
seen[field.Name] = struct{}{}
|
||||
if err := field.Type.Validate(); err != nil {
|
||||
return fmt.Errorf("field %s: %w", field.Name, err)
|
||||
}
|
||||
}
|
||||
case ValueEnum:
|
||||
if len(s.EnumValues) == 0 {
|
||||
return fmt.Errorf("enum values are required")
|
||||
}
|
||||
case ValueReference:
|
||||
if s.ReferenceKind == "" {
|
||||
return fmt.Errorf("reference kind is required")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package world
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestValueTypeSpecValidatesTypedRecursiveShape(t *testing.T) {
|
||||
spec := ValueTypeSpec{Kind: ValueStruct, Fields: []ValueField{{Name: "name", Type: ValueTypeSpec{Kind: ValueString}}, {Name: "refs", Type: ValueTypeSpec{Kind: ValueList, Element: &ValueTypeSpec{Kind: ValueReference, ReferenceKind: "world.object"}}}}}
|
||||
if err := spec.Validate(); err != nil {
|
||||
t.Fatalf("ValueTypeSpec.Validate() = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValueTypeSpecRejectsDuplicateFields(t *testing.T) {
|
||||
spec := ValueTypeSpec{Kind: ValueStruct, Fields: []ValueField{{Name: "same", Type: ValueTypeSpec{Kind: ValueString}}, {Name: "same", Type: ValueTypeSpec{Kind: ValueString}}}}
|
||||
if err := spec.Validate(); err == nil {
|
||||
t.Fatal("duplicate fields were accepted")
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"task_file": "dev/tasks/GEN2-001-accept-gen2-owner-registry-and-dependency-rules.json",
|
||||
"task_id": "GEN2-001",
|
||||
"task_file": "dev/tasks/GEN2-002-introduce-shared-gen2-data-primitives-without-shared-domain-semantics.json",
|
||||
"task_id": "GEN2-002",
|
||||
"task_revision": 1
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package clock
|
||||
|
||||
import "time"
|
||||
|
||||
// Instant is a UTC point represented as Unix milliseconds.
|
||||
type Instant int64
|
||||
|
||||
func (i Instant) Valid() bool { return i > 0 }
|
||||
|
||||
func NowInstant() Instant { return FromTime(time.Now().UTC()) }
|
||||
|
||||
func FromTime(value time.Time) Instant { return Instant(value.UTC().UnixMilli()) }
|
||||
|
||||
func (i Instant) Time() time.Time { return time.UnixMilli(int64(i)).UTC() }
|
||||
@@ -0,0 +1,14 @@
|
||||
package clock
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestInstantRoundTripUsesUTCUnixMilliseconds(t *testing.T) {
|
||||
want := time.Date(2026, time.August, 29, 12, 34, 56, 789000000, time.FixedZone("local", 3*60*60))
|
||||
got := FromTime(want).Time()
|
||||
if !got.Equal(want.UTC()) || got.Location() != time.UTC {
|
||||
t.Fatalf("instant round trip = %v, want %v UTC", got, want.UTC())
|
||||
}
|
||||
}
|
||||
+34
-5
@@ -6,14 +6,43 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ID is a transport-neutral opaque identifier primitive. Domain packages wrap it
|
||||
// in strong semantic ID types; do not pass bare ID across semantic boundaries.
|
||||
type ID string
|
||||
// StableID is a transport-neutral opaque identifier primitive. Domain packages
|
||||
// wrap it in strong semantic ID types; do not pass bare StableID across
|
||||
// semantic boundaries.
|
||||
type StableID string
|
||||
|
||||
func New() (ID, error) {
|
||||
// ID is retained as a compatibility name for the V1 primitive.
|
||||
type ID = StableID
|
||||
|
||||
// Revision is the optimistic version of a versioned semantic record.
|
||||
type Revision uint64
|
||||
|
||||
const InitialRevision Revision = 1
|
||||
|
||||
func (r Revision) Valid() bool { return r >= InitialRevision }
|
||||
|
||||
// SemanticRef is a technical cross-owner reference envelope. It identifies a
|
||||
// record but does not grant storage ownership or provide generic CRUD.
|
||||
type SemanticRef struct {
|
||||
OwnerNamespace string
|
||||
SemanticKind string
|
||||
StableID StableID
|
||||
Revision *Revision
|
||||
}
|
||||
|
||||
func (r SemanticRef) Valid() bool {
|
||||
return r.OwnerNamespace != "" && r.SemanticKind != "" && r.StableID != "" &&
|
||||
(r.Revision == nil || r.Revision.Valid())
|
||||
}
|
||||
|
||||
func NewStableID() (StableID, error) {
|
||||
var b [16]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return "", fmt.Errorf("generate id: %w", err)
|
||||
}
|
||||
return ID(hex.EncodeToString(b[:])), nil
|
||||
return StableID(hex.EncodeToString(b[:])), nil
|
||||
}
|
||||
|
||||
func New() (ID, error) {
|
||||
return NewStableID()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package ids
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestNewStableIDIsOpaque128BitHex(t *testing.T) {
|
||||
id, err := NewStableID()
|
||||
if err != nil || len(id) != 32 {
|
||||
t.Fatalf("NewStableID() = %q, %v", id, err)
|
||||
}
|
||||
if !(SemanticRef{OwnerNamespace: "world", SemanticKind: "object", StableID: id}.Valid()) {
|
||||
t.Fatal("stable id was not accepted by semantic reference")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSemanticRefRejectsInvalidRevision(t *testing.T) {
|
||||
revision := Revision(0)
|
||||
ref := SemanticRef{OwnerNamespace: "world", SemanticKind: "object", StableID: "id", Revision: &revision}
|
||||
if ref.Valid() {
|
||||
t.Fatal("semantic reference accepted invalid revision")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user