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_file": "dev/tasks/GEN2-002-introduce-shared-gen2-data-primitives-without-shared-domain-semantics.json",
|
||||||
"task_id": "GEN2-001",
|
"task_id": "GEN2-002",
|
||||||
"task_revision": 1
|
"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"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ID is a transport-neutral opaque identifier primitive. Domain packages wrap it
|
// StableID is a transport-neutral opaque identifier primitive. Domain packages
|
||||||
// in strong semantic ID types; do not pass bare ID across semantic boundaries.
|
// wrap it in strong semantic ID types; do not pass bare StableID across
|
||||||
type ID string
|
// 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
|
var b [16]byte
|
||||||
if _, err := rand.Read(b[:]); err != nil {
|
if _, err := rand.Read(b[:]); err != nil {
|
||||||
return "", fmt.Errorf("generate id: %w", err)
|
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