@opensoha/contracts 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/COMPATIBILITY.md +13 -0
  2. package/README.md +6 -0
  3. package/auth/catalog_generated.go +17 -0
  4. package/auth/catalog_test.go +53 -0
  5. package/auth/permission-catalog.json +10991 -0
  6. package/auth/permission-catalog.schema.json +74 -0
  7. package/compat/json-schema-ecosystem-0.1.0.json +1 -1
  8. package/compat/openapi-loose-boundaries-0.1.0.json +1 -1
  9. package/fixtures/json-schema/permission-catalog/invalid/missing-action.json +18 -0
  10. package/fixtures/json-schema/permission-catalog/valid/minimal.json +19 -0
  11. package/fixtures/openapi/AccessRoleInput/invalid/missing-permissions.json +4 -0
  12. package/fixtures/openapi/AccessRoleInput/valid/granular-vm-operator.json +10 -0
  13. package/fixtures/openapi/AuthorizationDecision/invalid/missing-reason.json +7 -0
  14. package/fixtures/openapi/AuthorizationDecision/valid/deny-vm-delete.json +16 -0
  15. package/fixtures/openapi/PermissionCatalogEnvelope/invalid/invalid-hash.json +8 -0
  16. package/fixtures/openapi/PermissionCatalogEnvelope/valid/minimal.json +22 -0
  17. package/fixtures/openapi/SecretCreateRequest/invalid/both-sources.json +12 -0
  18. package/fixtures/openapi/SecretCreateRequest/invalid/missing-vault-version.json +10 -0
  19. package/fixtures/openapi/SecretCreateRequest/invalid/vault-key-newline.json +11 -0
  20. package/fixtures/openapi/SecretCreateRequest/invalid/vault-key-whitespace.json +11 -0
  21. package/fixtures/openapi/SecretCreateRequest/valid/vault-kv2.json +11 -0
  22. package/fixtures/openapi/SecretRotateRequest/invalid/both-sources.json +9 -0
  23. package/fixtures/openapi/SecretRotateRequest/invalid/missing-source.json +1 -0
  24. package/fixtures/openapi/SecretRotateRequest/valid/vault-kv2.json +8 -0
  25. package/gen/go/sohaapi/client.go +1 -1
  26. package/gen/go/sohaapi/types.go +206 -9
  27. package/gen/ts/sohaapi/index.ts +333 -2
  28. package/openapi/soha-api.json +746 -5
  29. package/openapi/soha-api.yaml +297 -3
  30. package/openapi/spec_generated.go +3 -3
  31. package/package.json +7 -3
package/COMPATIBILITY.md CHANGED
@@ -281,6 +281,19 @@ rename `operationId`, `operationKind`, `runnerId`, `state`, `occurredAt`,
281
281
  `evidence`, `finalState`, or `callback`; must not add new required fields; and
282
282
  must not narrow existing lifecycle state names or final status values.
283
283
 
284
+ ## Permission Catalog
285
+
286
+ `auth/permission-catalog.json` owns grantable OpenSoha resource/action keys,
287
+ risk and scope metadata, approval posture, and temporary legacy aliases. Its
288
+ `contentHash` covers the ordered permission definitions; the Go `auth` package
289
+ also publishes the full artifact hash.
290
+
291
+ For `0.1.x`, patch releases may add active permission definitions and legacy
292
+ aliases. They must not remove active definitions, change an active key's
293
+ resource/action meaning, or make a legacy alias authorize a broader action.
294
+ Coarse keys become non-assignable before removal, and are removed only after
295
+ role migration and consumer conformance prove no active dependency.
296
+
284
297
  ## Consumer Adoption
285
298
 
286
299
  Recommended adoption flow:
package/README.md CHANGED
@@ -29,6 +29,8 @@ skills/skill-manifest.schema.json Official skill front matter contract
29
29
  plugins/plugin-manifest.schema.json Plugin and marketplace package manifest
30
30
  events/event-envelope.schema.json Shared event envelope contract
31
31
  auth/token-claims.schema.json Token/JWT claims contract
32
+ auth/permission-catalog.json Canonical resource/action permission catalog
33
+ auth/permission-catalog.schema.json Permission definition and migration metadata
32
34
  connectors/connector-event-envelope.schema.json Connector runtime event batch envelope
33
35
  gen/go/sohaapi Go SDK types for stable cross-repo contracts
34
36
  gen/ts/sohaapi TypeScript SDK types for stable Web contracts
@@ -78,6 +80,10 @@ npm run check:generated
78
80
  temporary directory and compares it to committed files. It must not rewrite
79
81
  generated files during a freshness check. The Go `openapi` package exposes
80
82
  copies of both formats plus `Version`, `YAMLSHA256`, and `JSONSHA256`.
83
+ The Go `auth` package embeds the canonical permission catalog and exposes its
84
+ catalog version, definition hash, and artifact hash. Refresh it with
85
+ `npm run generate:permissions`; consumers conformance-check their local keys
86
+ against this artifact instead of maintaining a second catalog.
81
87
 
82
88
  The Go client in `gen/go/sohaapi/client.go` intentionally keeps a stable
83
89
  hand-written method surface while DTOs are generated from OpenAPI. For
@@ -0,0 +1,17 @@
1
+ // Code generated from OpenSoha permission contracts. DO NOT EDIT.
2
+
3
+ package auth
4
+
5
+ import _ "embed"
6
+
7
+ const (
8
+ PermissionCatalogVersion = "1.2.0"
9
+ PermissionCatalogContentSHA256 = "5d7a468df65eb73a082457b0673b009034b5ed28f6a2fb4885b59a26fb7ca239"
10
+ PermissionCatalogSHA256 = "589f4abadceea081d9ca7b6508f38c55785bdc98496c6c9b2a2055e3abc58dd5"
11
+ )
12
+
13
+ //go:embed permission-catalog.json
14
+ var permissionCatalogJSON []byte
15
+
16
+ // PermissionCatalogJSON returns a copy of the canonical permission catalog.
17
+ func PermissionCatalogJSON() []byte { return append([]byte(nil), permissionCatalogJSON...) }
@@ -0,0 +1,53 @@
1
+ package auth
2
+
3
+ import (
4
+ "crypto/sha256"
5
+ "encoding/hex"
6
+ "encoding/json"
7
+ "testing"
8
+ )
9
+
10
+ func TestPermissionCatalogMetadataMatchesEmbeddedArtifact(t *testing.T) {
11
+ raw := PermissionCatalogJSON()
12
+ var catalog struct {
13
+ CatalogVersion string `json:"catalogVersion"`
14
+ ContentHash string `json:"contentHash"`
15
+ }
16
+ if err := json.Unmarshal(raw, &catalog); err != nil {
17
+ t.Fatalf("decode permission catalog: %v", err)
18
+ }
19
+ if catalog.CatalogVersion != PermissionCatalogVersion {
20
+ t.Fatalf("catalog version = %q, want %q", catalog.CatalogVersion, PermissionCatalogVersion)
21
+ }
22
+ if catalog.ContentHash != "sha256:"+PermissionCatalogContentSHA256 {
23
+ t.Fatalf("content hash = %q", catalog.ContentHash)
24
+ }
25
+ sum := sha256.Sum256(raw)
26
+ if got := hex.EncodeToString(sum[:]); got != PermissionCatalogSHA256 {
27
+ t.Fatalf("artifact hash = %q, want %q", got, PermissionCatalogSHA256)
28
+ }
29
+ }
30
+
31
+ func TestPermissionCatalogIncludesVirtualizationStorageView(t *testing.T) {
32
+ var catalog struct {
33
+ Permissions []struct {
34
+ Key string `json:"key"`
35
+ Action string `json:"action"`
36
+ RiskLevel string `json:"riskLevel"`
37
+ Status string `json:"status"`
38
+ Assignable bool `json:"assignable"`
39
+ } `json:"permissions"`
40
+ }
41
+ if err := json.Unmarshal(PermissionCatalogJSON(), &catalog); err != nil {
42
+ t.Fatalf("decode permission catalog: %v", err)
43
+ }
44
+ for _, permission := range catalog.Permissions {
45
+ if permission.Key == "virtualization.storage.view" {
46
+ if permission.Action != "view" || permission.RiskLevel != "read" || permission.Status != "active" || !permission.Assignable {
47
+ t.Fatalf("unexpected storage permission: %#v", permission)
48
+ }
49
+ return
50
+ }
51
+ }
52
+ t.Fatal("virtualization.storage.view is missing")
53
+ }