capsium 0.1.1 → 0.2.0

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +1 -4
  3. data/.github/workflows/release.yml +1 -2
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +34 -3
  6. data/CHANGELOG.md +58 -0
  7. data/Gemfile +4 -4
  8. data/LICENSE +21 -0
  9. data/README.adoc +177 -135
  10. data/Rakefile +8 -1
  11. data/bin/console +1 -1
  12. data/capsium.gemspec +16 -23
  13. data/exe/capsium +1 -1
  14. data/lib/capsium/cli/convert.rb +18 -0
  15. data/lib/capsium/cli/package.rb +86 -0
  16. data/lib/capsium/cli/reactor.rb +25 -0
  17. data/lib/capsium/cli.rb +5 -79
  18. data/lib/capsium/converters/jekyll.rb +62 -31
  19. data/lib/capsium/converters.rb +7 -0
  20. data/lib/capsium/package/dataset.rb +76 -56
  21. data/lib/capsium/package/manifest.rb +41 -50
  22. data/lib/capsium/package/manifest_config.rb +64 -0
  23. data/lib/capsium/package/metadata.rb +11 -29
  24. data/lib/capsium/package/metadata_config.rb +105 -0
  25. data/lib/capsium/package/routes.rb +51 -111
  26. data/lib/capsium/package/routes_config.rb +150 -0
  27. data/lib/capsium/package/security.rb +123 -0
  28. data/lib/capsium/package/security_config.rb +60 -0
  29. data/lib/capsium/package/storage.rb +26 -26
  30. data/lib/capsium/package/storage_config.rb +106 -0
  31. data/lib/capsium/package/validator.rb +149 -0
  32. data/lib/capsium/package.rb +84 -70
  33. data/lib/capsium/packager.rb +60 -62
  34. data/lib/capsium/reactor/introspection.rb +88 -0
  35. data/lib/capsium/reactor.rb +108 -36
  36. data/lib/capsium/version.rb +1 -1
  37. data/lib/capsium.rb +7 -9
  38. data/sig/capsium/package/dataset.rbs +28 -0
  39. data/sig/capsium/package/manifest.rbs +34 -0
  40. data/sig/capsium/package/manifest_config.rbs +38 -0
  41. data/sig/capsium/package/metadata.rbs +26 -0
  42. data/sig/capsium/package/metadata_config.rbs +49 -0
  43. data/sig/capsium/package/routes.rbs +37 -0
  44. data/sig/capsium/package/routes_config.rbs +74 -0
  45. data/sig/capsium/package/security.rbs +65 -0
  46. data/sig/capsium/package/security_config.rbs +57 -0
  47. data/sig/capsium/package/storage.rbs +28 -0
  48. data/sig/capsium/package/storage_config.rbs +61 -0
  49. data/sig/capsium/package/validator.rbs +29 -0
  50. data/sig/capsium/package.rbs +53 -0
  51. data/sig/capsium/packager.rbs +23 -0
  52. data/sig/capsium/reactor/introspection.rbs +31 -0
  53. data/sig/capsium/reactor.rbs +30 -0
  54. data/sig/capsium.rbs +3 -1
  55. metadata +63 -146
  56. data/images/005df7415a331c466ad2d9a42efdd212b6f42fe50b5fd3b3174c86c706f58244.png +0 -0
  57. data/images/0374025b3af99b8a473282c8cbbf9fcd29573cf41e586982f328f86c0690f43d.png +0 -0
  58. data/images/0bb4da785be40ef58e219470ebccb979325928b75453dc46bac23c6ee8a7a7cb.png +0 -0
  59. data/images/6aa294dccc81af594aacbe804e7ddffdc17eacc28357338108aea5d021d831ff.png +0 -0
  60. data/images/72dd3fbf3f4b475e27a0e7fb8137c475c32c41f8d222bcf62d6a9ccf102d9532.png +0 -0
  61. data/images/8772b6961d169738d7b0fa0b669b06fc2f40632d4c62586c7634fc17b93182a3.png +0 -0
  62. data/images/a998d842405933d45723606ff3f70162ec95b4ef30db25464a366184fd08fb9b.png +0 -0
  63. data/images/aa8980547e8c003d33273ab4d80e62da7f317bd7581b293c06d67f5331f24f31.png +0 -0
  64. data/images/bb78a872b539e0e9b2d80dee58acbb688f3f2727b324a5bf8bf417a69d94a166.png +0 -0
  65. data/images/c48fc83b17725d85fbb64d971196ebfccd8c5c757fe6aa5845303f6e315879b6.png +0 -0
  66. data/images/f08ef07308d08119ac2124bb7428c8bef17ef1ca70045696604d6e83015a9b91.png +0 -0
  67. data/images/f7514206111b695647eae9adfcf498ba3e0ff83ecfe25f3fc3ed8e9f04c5c726-1.png +0 -0
  68. data/images/f7514206111b695647eae9adfcf498ba3e0ff83ecfe25f3fc3ed8e9f04c5c726.png +0 -0
  69. data/lib/capsium/protector.rb +0 -95
data/lib/capsium.rb CHANGED
@@ -1,15 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "capsium/version"
4
- require "shale"
5
- require "shale/adapter/nokogiri"
6
- Shale.xml_adapter = Shale::Adapter::Nokogiri
7
-
8
3
  module Capsium
9
4
  class Error < StandardError; end
10
5
 
11
- # Your code goes here...
6
+ autoload :VERSION, "capsium/version"
7
+ autoload :Cli, "capsium/cli"
8
+ autoload :Converters, "capsium/converters"
9
+ autoload :Package, "capsium/package"
10
+ autoload :Packager, "capsium/packager"
11
+ autoload :Reactor, "capsium/reactor"
12
+ autoload :ThorExt, "capsium/thor_ext"
12
13
  end
13
-
14
- require_relative "capsium/package"
15
- require_relative "capsium/packager"
@@ -0,0 +1,28 @@
1
+ module Capsium
2
+ class Package
3
+ # A loaded dataset. "source"/"schemaFile"/"databaseFile" are
4
+ # package-relative paths resolved against the package directory.
5
+ class Dataset
6
+ attr_reader name: String
7
+ attr_reader config: DatasetConfig
8
+ attr_reader data: untyped
9
+ attr_reader package_path: String
10
+
11
+ def initialize: (name: String name, config: DatasetConfig config,
12
+ package_path: String package_path) -> void
13
+
14
+ def source_path: () -> String
15
+
16
+ def schema_path: () -> String?
17
+
18
+ def load_data: () -> untyped
19
+
20
+ def validate: () -> bool
21
+
22
+ # File-existence and schema validations; empty when valid.
23
+ def validation_errors: () -> Array[String]
24
+
25
+ def to_json: (*untyped args) -> String
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,34 @@
1
+ module Capsium
2
+ class Package
3
+ # Loads, generates and writes manifest.json (ARCHITECTURE.md
4
+ # section 3).
5
+ class Manifest
6
+ attr_reader path: String
7
+ attr_reader content_path: String
8
+ attr_reader config: ManifestConfig
9
+
10
+ def initialize: (String path) -> void
11
+
12
+ # Auto-generation: scan content/ recursively, detect MIME types,
13
+ # default visibility "exported", deterministic (sorted) output.
14
+ def generate_manifest: () -> Hash[String, Resource]
15
+
16
+ def resources: () -> Hash[String, Resource]
17
+
18
+ def lookup: (String path) -> Resource?
19
+
20
+ def type_for: (String path) -> String?
21
+
22
+ def to_json: (*untyped args) -> String
23
+ def to_hash: () -> Hash[String, untyped]
24
+
25
+ def save_to_file: (?String output_path) -> void
26
+
27
+ def path_to_content_file: (String path) -> Pathname
28
+
29
+ def content_file_exists?: (String path) -> bool
30
+
31
+ def relative_path: (String path) -> String
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,38 @@
1
+ module Capsium
2
+ class Package
3
+ # A single manifest resource entry (ARCHITECTURE.md section 3).
4
+ class Resource
5
+ VISIBILITIES: Array[String]
6
+
7
+ attr_accessor type: String?
8
+ attr_accessor visibility: String
9
+ attr_accessor version: String?
10
+
11
+ def initialize: (?type: String? type, ?visibility: String? visibility,
12
+ ?version: String? version) -> void
13
+
14
+ def to_json: (*untyped args) -> String
15
+ def to_hash: () -> Hash[String, untyped]
16
+ end
17
+
18
+ # Canonical manifest.json model: an object keyed by package-relative
19
+ # resource path. The legacy array form is normalized on read;
20
+ # writers emit only the object form.
21
+ class ManifestConfig
22
+ attr_accessor resources: Hash[String, Resource]
23
+
24
+ def initialize: (?resources: Hash[String, Resource] resources) -> void
25
+
26
+ def self.from_json: (String json) -> instance
27
+
28
+ def resources_from_json: (ManifestConfig model, untyped value) -> void
29
+
30
+ def resources_to_json: (ManifestConfig model, Hash[String, untyped] doc) -> void
31
+
32
+ def sort!: () -> ManifestConfig
33
+
34
+ def to_json: (*untyped args) -> String
35
+ def to_hash: () -> Hash[String, untyped]
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,26 @@
1
+ module Capsium
2
+ class Package
3
+ # Loads and writes metadata.json; field access is delegated to the
4
+ # wrapped MetadataData config (ARCHITECTURE.md section 2).
5
+ class Metadata
6
+ attr_reader path: String
7
+ attr_reader config: MetadataData
8
+
9
+ def initialize: (String path) -> void
10
+
11
+ def save_to_file: (?String output_path) -> void
12
+
13
+ def to_json: (*untyped args) -> String
14
+ def to_hash: () -> Hash[String, untyped]
15
+ def name: () -> String?
16
+ def version: () -> String?
17
+ def description: () -> String?
18
+ def guid: () -> String?
19
+ def uuid: () -> String?
20
+ def author: () -> String?
21
+ def license: () -> String?
22
+ def repository: () -> Repository?
23
+ def dependencies: () -> Hash[String, String]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,49 @@
1
+ module Capsium
2
+ class Package
3
+ # The repository object of metadata.json.
4
+ class Repository
5
+ attr_accessor type: String?
6
+ attr_accessor url: String?
7
+
8
+ def initialize: (?type: String? type, ?url: String? url) -> void
9
+
10
+ def to_json: (*untyped args) -> String
11
+ def to_hash: () -> Hash[String, untyped]
12
+ end
13
+
14
+ # Canonical metadata.json model (ARCHITECTURE.md section 2). The
15
+ # legacy array form of "dependencies" is normalized on read; writers
16
+ # emit only the object form.
17
+ class MetadataData
18
+ KEBAB_CASE_PATTERN: Regexp
19
+ SEMVER_PATTERN: Regexp
20
+ UUID_PATTERN: Regexp
21
+
22
+ attr_accessor name: String?
23
+ attr_accessor version: String?
24
+ attr_accessor description: String?
25
+ attr_accessor guid: String?
26
+ attr_accessor uuid: String?
27
+ attr_accessor author: String?
28
+ attr_accessor license: String?
29
+ attr_accessor repository: Repository?
30
+ attr_accessor dependencies: Hash[String, String]
31
+ attr_accessor read_only: bool?
32
+
33
+ def initialize: (?name: String? name, ?version: String? version,
34
+ ?description: String? description, ?guid: String? guid,
35
+ ?uuid: String? uuid, ?author: String? author,
36
+ ?license: String? license, ?repository: Repository? repository,
37
+ ?dependencies: Hash[String, String] dependencies,
38
+ ?read_only: bool? read_only) -> void
39
+
40
+ def self.from_json: (String json) -> instance
41
+
42
+ # Field-level format validations; empty when valid.
43
+ def format_errors: () -> Array[String]
44
+
45
+ def to_json: (*untyped args) -> String
46
+ def to_hash: () -> Hash[String, untyped]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,37 @@
1
+ module Capsium
2
+ class Package
3
+ # Loads, generates and writes routes.json (ARCHITECTURE.md
4
+ # section 4).
5
+ class Routes
6
+ INDEX_ROUTE: String
7
+ INDEX_RESOURCE: String
8
+ DATASET_ROUTE_PREFIX: String
9
+
10
+ attr_reader path: String
11
+ attr_reader config: RoutesConfig
12
+ attr_reader manifest: Manifest
13
+ attr_reader storage: Storage
14
+
15
+ def initialize: (String path, Manifest manifest, Storage storage) -> void
16
+
17
+ def resolve: (String url_path) -> Route?
18
+
19
+ def add_route: (String route, String target) -> Route
20
+
21
+ def update_route: (String route, String updated_route, String updated_target) -> Route
22
+
23
+ def remove_route: (String route) -> Array[Route]
24
+
25
+ def to_json: (*untyped args) -> String
26
+ def to_hash: () -> Hash[String, untyped]
27
+
28
+ def save_to_file: (?String output_path) -> void
29
+
30
+ # Auto-generation (ARCHITECTURE.md section 4): every manifest
31
+ # resource gets a route at its path relative to content/; HTML
32
+ # files get two routes; the index HTML additionally gets "/";
33
+ # every dataset gets /api/v1/data/<id>. Deterministic output.
34
+ def generate_routes: () -> RoutesConfig
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,74 @@
1
+ module Capsium
2
+ class Package
3
+ # A single route entry (ARCHITECTURE.md section 4). Kinds are
4
+ # discriminated by key, MECE: static file, dataset route, or dynamic
5
+ # handler (accepted-and-ignored; reactors respond 501).
6
+ class Route
7
+ DATASET_PATH_PREFIX: String
8
+
9
+ attr_accessor path: String?
10
+ attr_accessor resource: String?
11
+ attr_accessor headers: Hash[String, String]?
12
+ attr_accessor headers_file: String?
13
+ attr_accessor visibility: String
14
+ attr_accessor dataset: String?
15
+ attr_accessor access_control: Hash[String, untyped]?
16
+ attr_accessor http_method: String?
17
+ attr_accessor handler: String?
18
+
19
+ def initialize: (?path: String? path, ?resource: String? resource,
20
+ ?headers: Hash[String, String]? headers,
21
+ ?headers_file: String? headers_file,
22
+ ?visibility: String? visibility, ?dataset: String? dataset,
23
+ ?access_control: Hash[String, untyped]? access_control,
24
+ ?http_method: String? http_method,
25
+ ?handler: String? handler) -> void
26
+
27
+ def self.from_json: (String json) -> instance
28
+
29
+ def kind: () -> (:resource | :dataset | :handler)
30
+
31
+ def dataset_route?: () -> bool
32
+
33
+ def handler_route?: () -> bool
34
+
35
+ def fs_path: (String package_path) -> String?
36
+
37
+ def mime: (Manifest manifest) -> String?
38
+
39
+ def validate_target: (String package_path, Storage storage) -> void
40
+
41
+ def to_json: (*untyped args) -> String
42
+ def to_hash: () -> Hash[String, untyped]
43
+ end
44
+
45
+ # Canonical routes.json model: optional top-level "index" plus a
46
+ # "routes" array. The legacy object/target form is normalized on
47
+ # read; writers emit only the canonical form.
48
+ class RoutesConfig
49
+ attr_accessor index: String?
50
+ attr_accessor routes: Array[Route]
51
+
52
+ def initialize: (?index: String? index, ?routes: Array[Route] routes) -> void
53
+
54
+ def self.from_json: (String json) -> instance
55
+
56
+ def routes_from_json: (RoutesConfig model, untyped value) -> void
57
+
58
+ def routes_to_json: (RoutesConfig model, Hash[String, untyped] doc) -> void
59
+
60
+ def resolve: (String path) -> Route?
61
+
62
+ def add: (String path, String target) -> Route
63
+
64
+ def update: (String path, String updated_path, String updated_target) -> Route
65
+
66
+ def remove: (String path) -> Array[Route]
67
+
68
+ def sort!: () -> RoutesConfig
69
+
70
+ def to_json: (*untyped args) -> String
71
+ def to_hash: () -> Hash[String, untyped]
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,65 @@
1
+ module Capsium
2
+ class Package
3
+ # Loads, generates and verifies security.json (ARCHITECTURE.md
4
+ # section 6). Checksums cover every file in the package except
5
+ # security.json itself.
6
+ class Security
7
+ class IntegrityError < Capsium::Error
8
+ end
9
+
10
+ # A file whose SHA-256 does not match the recorded checksum.
11
+ class ChecksumMismatch
12
+ attr_reader path: String
13
+ attr_reader expected: String
14
+ attr_reader actual: String
15
+
16
+ def initialize: (path: String path, expected: String expected, actual: String actual) -> void
17
+
18
+ def message: () -> String
19
+ end
20
+
21
+ # A checksum listed for a file that is missing on disk.
22
+ class MissingFile
23
+ attr_reader path: String
24
+ attr_reader expected: String
25
+
26
+ def initialize: (path: String path, expected: String expected) -> void
27
+
28
+ def message: () -> String
29
+ end
30
+
31
+ # A file on disk not covered by any checksum.
32
+ class UncheckedFile
33
+ attr_reader path: String
34
+
35
+ def initialize: (path: String path) -> void
36
+
37
+ def message: () -> String
38
+ end
39
+
40
+ attr_reader path: String
41
+ attr_reader config: SecurityConfig?
42
+
43
+ def initialize: (String path, ?SecurityConfig? config) -> void
44
+
45
+ def self.generate: (String package_path) -> Security
46
+
47
+ def self.checksums_for: (String package_path) -> Hash[String, String]
48
+
49
+ def self.package_files: (String package_path) -> Array[String]
50
+
51
+ def present?: () -> bool
52
+
53
+ def checksums: () -> Hash[String, String]
54
+
55
+ def verify: (String package_path) -> Array[ChecksumMismatch | MissingFile | UncheckedFile]
56
+
57
+ def verify!: (String package_path) -> void
58
+
59
+ def save_to_file: (?String output_path) -> void
60
+
61
+ def to_json: (*untyped args) -> String
62
+ def to_hash: () -> Hash[String, untyped]
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,57 @@
1
+ module Capsium
2
+ class Package
3
+ # The "integrityChecks" object of security.json: SHA-256 checksums
4
+ # keyed by package-relative path.
5
+ class IntegrityChecks
6
+ ALGORITHMS: Array[String]
7
+
8
+ attr_accessor checksum_algorithm: String
9
+ attr_accessor checksums: Hash[String, String]
10
+
11
+ def initialize: (?checksum_algorithm: String? checksum_algorithm,
12
+ ?checksums: Hash[String, String] checksums) -> void
13
+
14
+ def to_json: (*untyped args) -> String
15
+ def to_hash: () -> Hash[String, untyped]
16
+ end
17
+
18
+ # The "digitalSignatures" object of security.json (parsed only;
19
+ # signing is a later phase).
20
+ class DigitalSignatures
21
+ attr_accessor public_key: String?
22
+ attr_accessor signature_file: String?
23
+
24
+ def initialize: (?public_key: String? public_key,
25
+ ?signature_file: String? signature_file) -> void
26
+
27
+ def to_json: (*untyped args) -> String
28
+ def to_hash: () -> Hash[String, untyped]
29
+ end
30
+
31
+ # The "security" object of security.json.
32
+ class SecurityData
33
+ attr_accessor integrity_checks: IntegrityChecks?
34
+ attr_accessor digital_signatures: DigitalSignatures?
35
+
36
+ def initialize: (?integrity_checks: IntegrityChecks? integrity_checks,
37
+ ?digital_signatures: DigitalSignatures? digital_signatures) -> void
38
+
39
+ def to_json: (*untyped args) -> String
40
+ def to_hash: () -> Hash[String, untyped]
41
+ end
42
+
43
+ # Canonical security.json model (generated at pack time).
44
+ class SecurityConfig
45
+ attr_accessor security: SecurityData?
46
+
47
+ def initialize: (?security: SecurityData? security) -> void
48
+
49
+ def self.from_json: (String json) -> instance
50
+
51
+ def checksums: () -> Hash[String, String]
52
+
53
+ def to_json: (*untyped args) -> String
54
+ def to_hash: () -> Hash[String, untyped]
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,28 @@
1
+ module Capsium
2
+ class Package
3
+ # Loads and writes storage.json and instantiates its datasets
4
+ # (ARCHITECTURE.md section 5).
5
+ class Storage
6
+ attr_reader path: String
7
+ attr_reader config: StorageConfig
8
+ attr_reader datasets: Array[Dataset]
9
+
10
+ def initialize: (String path) -> void
11
+
12
+ def data_sets: () -> Hash[String, DatasetConfig]
13
+
14
+ def load_datasets: () -> Array[Dataset]
15
+
16
+ def dataset: (String name) -> Dataset?
17
+
18
+ def dataset_names: () -> Array[String]
19
+
20
+ def empty?: () -> bool
21
+
22
+ def save_to_file: (?String output_path) -> void
23
+
24
+ def to_json: (*untyped args) -> String
25
+ def to_hash: () -> Hash[String, untyped]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,61 @@
1
+ module Capsium
2
+ class Package
3
+ # A single dataset entry (ARCHITECTURE.md section 5): schema-backed
4
+ # file (via "source") or SQLite ("databaseFile" + "table").
5
+ class DatasetConfig
6
+ FORMATS: Hash[String, String]
7
+ SCHEMA_TYPES: Array[String]
8
+
9
+ attr_accessor source: String?
10
+ attr_accessor schema_file: String?
11
+ attr_accessor schema_type: String?
12
+ attr_accessor database_file: String?
13
+ attr_accessor table: String?
14
+
15
+ def initialize: (?source: String? source, ?schema_file: String? schema_file,
16
+ ?schema_type: String? schema_type,
17
+ ?database_file: String? database_file,
18
+ ?table: String? table) -> void
19
+
20
+ def format: () -> String
21
+
22
+ def sqlite?: () -> bool
23
+
24
+ def backing_file: () -> String
25
+
26
+ def to_dataset: (String name, String package_path) -> Dataset
27
+
28
+ def to_json: (*untyped args) -> String
29
+ def to_hash: () -> Hash[String, untyped]
30
+ end
31
+
32
+ # The "storage" object holding the dataSets map.
33
+ class StorageData
34
+ attr_accessor data_sets: Hash[String, DatasetConfig]
35
+
36
+ def initialize: (?data_sets: Hash[String, DatasetConfig] data_sets) -> void
37
+
38
+ def data_sets_from_json: (StorageData model, untyped value) -> void
39
+
40
+ def data_sets_to_json: (StorageData model, Hash[String, untyped] doc) -> void
41
+
42
+ def to_json: (*untyped args) -> String
43
+ def to_hash: () -> Hash[String, untyped]
44
+ end
45
+
46
+ # Canonical storage.json model. The legacy array form is normalized
47
+ # on read; writers emit only the canonical form.
48
+ class StorageConfig
49
+ attr_accessor storage: StorageData?
50
+
51
+ def initialize: (?storage: StorageData? storage) -> void
52
+
53
+ def self.from_json: (String json) -> instance
54
+
55
+ def data_sets: () -> Hash[String, DatasetConfig]
56
+
57
+ def to_json: (*untyped args) -> String
58
+ def to_hash: () -> Hash[String, untyped]
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,29 @@
1
+ module Capsium
2
+ class Package
3
+ # Validates a package directory or .cap file against the canonical
4
+ # schemas (ARCHITECTURE.md sections 2-6) and reports one result per
5
+ # check. Used by `capsium package validate`.
6
+ class Validator
7
+ EXTERNAL_REFERENCE_PATTERN: Regexp
8
+ TEXT_CONTENT_MIME: Regexp
9
+
10
+ # One named validation check with its problems; ok when messages
11
+ # is empty.
12
+ class CheckResult
13
+ attr_reader name: String
14
+ attr_reader ok: bool
15
+ attr_reader messages: Array[String]
16
+
17
+ def initialize: (name: String name, ok: bool ok, messages: Array[String] messages) -> void
18
+
19
+ def ok?: () -> bool
20
+ end
21
+
22
+ def initialize: (String package_path) -> void
23
+
24
+ def run: () -> Array[CheckResult]
25
+
26
+ def valid?: () -> bool
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,53 @@
1
+ module Capsium
2
+ # A Capsium package loaded from a directory or a .cap file
3
+ # (ARCHITECTURE.md section 1).
4
+ class Package
5
+ MANIFEST_FILE: String
6
+ METADATA_FILE: String
7
+ STORAGE_FILE: String
8
+ ROUTES_FILE: String
9
+ SECURITY_FILE: String
10
+ CONTENT_DIR: String
11
+ DATA_DIR: String
12
+
13
+ attr_reader name: String
14
+ attr_reader path: String
15
+ attr_reader manifest: Manifest
16
+ attr_reader metadata: Metadata
17
+ attr_reader routes: Routes
18
+ attr_reader storage: Storage
19
+ attr_reader security: Security
20
+ attr_reader load_type: Symbol
21
+
22
+ def initialize: (String | Pathname path, ?load_type: Symbol? load_type) -> void
23
+
24
+ def prepare_package: (Pathname path) -> (String | Pathname)
25
+
26
+ def solidify: () -> void
27
+
28
+ def decompress_cap_file: (String | Pathname file_path) -> String
29
+
30
+ def load_package: () -> void
31
+
32
+ # Removes the temporary extraction directory of a .cap-loaded
33
+ # package; a no-op for directory loads.
34
+ def cleanup: () -> void
35
+
36
+ def datasets: () -> Array[Dataset]
37
+
38
+ # The .cap file this package was loaded from, or nil when loaded
39
+ # from a directory.
40
+ def cap_file_path: () -> String?
41
+
42
+ def content_files: () -> Array[String]
43
+
44
+ def determine_load_type: (String | Pathname path) -> Symbol
45
+
46
+ # Verifies the package against security.json (ARCHITECTURE.md
47
+ # section 6). Returns a list of typed errors; empty when no
48
+ # security.json is present or all checksums match.
49
+ def verify_integrity: () -> Array[Security::ChecksumMismatch | Security::MissingFile | Security::UncheckedFile]
50
+
51
+ def verify_integrity!: () -> void
52
+ end
53
+ end
@@ -0,0 +1,23 @@
1
+ module Capsium
2
+ # Packs a package directory into a .cap file (generating
3
+ # security.json) and unpacks .cap files with zip-slip protection.
4
+ class Packager
5
+ class FileAlreadyExistsError < StandardError
6
+ end
7
+
8
+ # Raised when a .cap archive contains an entry whose name would be
9
+ # written outside the destination directory (zip-slip).
10
+ class UnsafeEntryError < Capsium::Error
11
+ end
12
+
13
+ DRIVE_LETTER_PATTERN: Regexp
14
+
15
+ def pack: (Package package, ?Hash[Symbol, untyped] options) -> String
16
+
17
+ def unpack: (String cap_file_path, String destination) -> void
18
+
19
+ def compress_package: (Package package, String cap_file) -> void
20
+
21
+ def relative_path_current: (String absolute_path) -> String
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ module Capsium
2
+ class Reactor
3
+ # Monitoring HTTP API reports for the package this reactor serves
4
+ # (ARCHITECTURE.md section 7).
5
+ class Introspection
6
+ METADATA_PATH: String
7
+ ROUTES_PATH: String
8
+ CONTENT_HASHES_PATH: String
9
+ CONTENT_VALIDITY_PATH: String
10
+ PATHS: Array[String]
11
+
12
+ attr_reader package: Package
13
+
14
+ def initialize: (Package package) -> void
15
+
16
+ def endpoint?: (String path) -> bool
17
+
18
+ # The report body for an introspection endpoint, or nil when the
19
+ # path is not an introspection endpoint.
20
+ def report_for: (String path) -> Hash[Symbol, untyped]?
21
+
22
+ def metadata_report: () -> Hash[Symbol, untyped]
23
+
24
+ def routes_report: () -> Hash[Symbol, untyped]
25
+
26
+ def content_hashes_report: () -> Hash[Symbol, untyped]
27
+
28
+ def content_validity_report: () -> Hash[Symbol, untyped]
29
+ end
30
+ end
31
+ end