jpie 3.5.0 → 3.7.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.
- checksums.yaml +4 -4
- data/.claude/skills/writing-discipline/SKILL.md +55 -0
- data/CLAUDE.md +34 -0
- data/Gemfile.lock +1 -1
- data/lib/json_api/controllers/concerns/resource_actions/serialization.rb +3 -2
- data/lib/json_api/serialization/concerns/include_filtering.rb +15 -3
- data/lib/json_api/serialization/concerns/includes_serialization.rb +19 -2
- data/lib/json_api/serialization/serializer.rb +4 -2
- data/lib/json_api/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7afd23e7e9ffb26be73d59ec5776b05d0a1375edc172c8faf8ee8675c1a9e681
|
|
4
|
+
data.tar.gz: d0b2ac2e8bb3035829524faabc24d2eb787cb0f716e66e3f008043b42a3c31fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: de7034c8a695bb8a27501f8c00129a8b4465c3ac7963da3a3327c634b5c85064b29dfbd232841a27a84e15c1b2ef477e1ecf24bae4752ab704f8b76919dba806
|
|
7
|
+
data.tar.gz: b3474c65fcd26816af5f8f02766f8a52e850112919e29f14b1deff31f5bbc785bbf12dd24d331af4cc321f086f45c06d7ed47b068fd90158d3765b0eda5a631f
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: writing-discipline
|
|
3
|
+
description: The writing standard for all prose — chat responses, documentation, code comments, commit messages, PR descriptions, Jira and Slack posts. Use BEFORE you write any human-facing text. Enforces ASD-STE100 (Simplified Technical English) plus Orwell's six rules — active voice, short sentences, short everyday words, one instruction per sentence, no idioms, no jargon, cut every word you can.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Writing discipline
|
|
7
|
+
|
|
8
|
+
All prose obeys ASD-STE100 (Simplified Technical English) and Orwell's six rules of
|
|
9
|
+
writing. This covers chat responses, documentation, code comments, commit messages,
|
|
10
|
+
PR descriptions, and Jira and Slack posts.
|
|
11
|
+
|
|
12
|
+
## ASD-STE100
|
|
13
|
+
|
|
14
|
+
- Use only approved words from the STE dictionary (one word, one meaning). Technical
|
|
15
|
+
names and technical verbs of this domain are permitted.
|
|
16
|
+
- Write in the active voice. Use the present tense where possible.
|
|
17
|
+
- Keep sentences short: maximum 20 words in an instruction, maximum 25 words in
|
|
18
|
+
descriptive text.
|
|
19
|
+
- Give one instruction per sentence. Start an instruction with the command form of
|
|
20
|
+
the verb.
|
|
21
|
+
- Do not make noun clusters of more than three nouns.
|
|
22
|
+
- Do not use slang, idioms, or Latin abbreviations (no "e.g.", "i.e.", "etc.", "via").
|
|
23
|
+
- Use a vertical list when you give more than three facts or steps in sequence.
|
|
24
|
+
- Start a warning or caution with the command, not the explanation.
|
|
25
|
+
|
|
26
|
+
## Orwell's six rules
|
|
27
|
+
|
|
28
|
+
1. Never use a metaphor, simile, or other figure of speech which you are used to
|
|
29
|
+
seeing in print.
|
|
30
|
+
2. Never use a long word where a short one will do.
|
|
31
|
+
3. If it is possible to cut a word out, always cut it out.
|
|
32
|
+
4. Never use the passive where you can use the active.
|
|
33
|
+
5. Never use a foreign phrase, a scientific word, or a jargon word if you can think
|
|
34
|
+
of an everyday English equivalent.
|
|
35
|
+
6. Break any of these rules sooner than say anything outright barbarous.
|
|
36
|
+
|
|
37
|
+
## How to apply
|
|
38
|
+
|
|
39
|
+
- Draft, then cut. Remove every word that does not change the meaning.
|
|
40
|
+
- Break a long sentence at "which", "and", or "but".
|
|
41
|
+
- Prefer a verb to a noun cluster: write "when the job runs", not "at job execution
|
|
42
|
+
time".
|
|
43
|
+
- Replace idioms with plain statements: write "this shows the cause", not "this is
|
|
44
|
+
the smoking gun".
|
|
45
|
+
- Replace Latin abbreviations: write "for example", not "e.g."; name the items, or
|
|
46
|
+
write "and more", instead of "etc.".
|
|
47
|
+
- Keep technical names, commands, and code identifiers as they are. The standard
|
|
48
|
+
limits prose, not identifiers.
|
|
49
|
+
|
|
50
|
+
## Self-check before you send
|
|
51
|
+
|
|
52
|
+
- Is every sentence inside the length limit?
|
|
53
|
+
- Is every verb active?
|
|
54
|
+
- Can any word go?
|
|
55
|
+
- Does a reader who is not an expert know every word that is not a technical name?
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Writing standard: ASD-STE100 + Orwell's six rules
|
|
6
|
+
|
|
7
|
+
All prose you write — chat responses, documentation, code comments, commit messages,
|
|
8
|
+
PR descriptions, Jira and Slack posts — must obey ASD-STE100 (Simplified Technical
|
|
9
|
+
English) and Orwell's six rules of writing.
|
|
10
|
+
|
|
11
|
+
ASD-STE100:
|
|
12
|
+
|
|
13
|
+
- Use only approved words from the STE dictionary (one word, one meaning). Technical
|
|
14
|
+
names and technical verbs of this domain are permitted.
|
|
15
|
+
- Write in the active voice. Use the present tense where possible.
|
|
16
|
+
- Keep sentences short: maximum 20 words in an instruction, maximum 25 words in
|
|
17
|
+
descriptive text.
|
|
18
|
+
- Give one instruction per sentence. Start an instruction with the command form of
|
|
19
|
+
the verb.
|
|
20
|
+
- Do not make noun clusters of more than three nouns.
|
|
21
|
+
- Do not use slang, idioms, or Latin abbreviations (no "e.g.", "i.e.", "etc.", "via").
|
|
22
|
+
- Use a vertical list when you give more than three facts or steps in sequence.
|
|
23
|
+
- Start a warning or caution with the command, not the explanation.
|
|
24
|
+
|
|
25
|
+
Orwell's six rules:
|
|
26
|
+
|
|
27
|
+
1. Never use a metaphor, simile, or other figure of speech which you are used to
|
|
28
|
+
seeing in print.
|
|
29
|
+
2. Never use a long word where a short one will do.
|
|
30
|
+
3. If it is possible to cut a word out, always cut it out.
|
|
31
|
+
4. Never use the passive where you can use the active.
|
|
32
|
+
5. Never use a foreign phrase, a scientific word, or a jargon word if you can think
|
|
33
|
+
of an everyday English equivalent.
|
|
34
|
+
6. Break any of these rules sooner than say anything outright barbarous.
|
data/Gemfile.lock
CHANGED
|
@@ -7,7 +7,7 @@ module JSONAPI
|
|
|
7
7
|
include IncludePreloading
|
|
8
8
|
|
|
9
9
|
def serialize_resource(resource)
|
|
10
|
-
JSONAPI::Serializer.new(resource).to_hash(
|
|
10
|
+
JSONAPI::Serializer.new(resource, authorization_context: self).to_hash(
|
|
11
11
|
include: parse_include_param,
|
|
12
12
|
fields: parse_fields_param,
|
|
13
13
|
document_meta: jsonapi_document_meta,
|
|
@@ -42,7 +42,8 @@ module JSONAPI
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def serialize_single(resource, includes, fields)
|
|
45
|
-
JSONAPI::Serializer.new(resource).to_hash(include: includes, fields:,
|
|
45
|
+
JSONAPI::Serializer.new(resource, authorization_context: self).to_hash(include: includes, fields:,
|
|
46
|
+
document_meta: nil,)
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def collect_included(result, all_included, processed)
|
|
@@ -7,10 +7,22 @@ module JSONAPI
|
|
|
7
7
|
loaded_array = association.target.respond_to?(:to_a) ? association.target.to_a : Array(association.target)
|
|
8
8
|
return [] if loaded_array.empty?
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
base_scope = ResourceLoader.find_for_model(related_klass).records
|
|
11
|
+
authorized_scope = apply_include_authorization(base_scope, related_klass)
|
|
12
|
+
|
|
13
|
+
# When the authorization_scope hook narrows the relation (joins/subqueries a
|
|
14
|
+
# where-hash can't express), the eager-loaded set — preloaded through acts_as_tenant
|
|
15
|
+
# alone — must be re-checked against the authorized scope in the database, so a
|
|
16
|
+
# relationship never surfaces a record the related endpoint denies. An unchanged
|
|
17
|
+
# scope keeps the in-memory, query-free records-only filtering.
|
|
18
|
+
return filter_by_query(loaded_array, authorized_scope) if narrowed?(base_scope, authorized_scope)
|
|
19
|
+
return loaded_array if base_scope.where_clause.empty?
|
|
20
|
+
|
|
21
|
+
filter_by_where_hash(loaded_array, base_scope, related_klass)
|
|
22
|
+
end
|
|
12
23
|
|
|
13
|
-
|
|
24
|
+
def narrowed?(base_scope, authorized_scope)
|
|
25
|
+
authorized_scope.to_sql != base_scope.to_sql
|
|
14
26
|
end
|
|
15
27
|
|
|
16
28
|
def filter_by_where_hash(loaded_array, resource_scope, related_klass)
|
|
@@ -96,7 +96,23 @@ module JSONAPI
|
|
|
96
96
|
|
|
97
97
|
def build_scoped_relation(related_klass, association)
|
|
98
98
|
related_base_scope = ResourceLoader.find_for_model(related_klass).records
|
|
99
|
-
association.scope.merge(related_base_scope)
|
|
99
|
+
association.scope.merge(apply_include_authorization(related_base_scope, related_klass))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# A sideloaded `?include=` is loaded through acts_as_tenant alone, bypassing the
|
|
103
|
+
# related resource's authorization_scope — so a relationship can reach records the
|
|
104
|
+
# related resource's own collection endpoint denies (e.g. an include that surfaces
|
|
105
|
+
# rows a Pundit scope hides). Route the related resource's base records through the
|
|
106
|
+
# configured authorization_scope hook, exactly as the primary collection does, so an
|
|
107
|
+
# included record can never escape the reader's authorization. No context (serializer
|
|
108
|
+
# used outside a request) or no configured hook leaves the scope untouched.
|
|
109
|
+
def apply_include_authorization(scope, model_class)
|
|
110
|
+
return scope unless authorization_context
|
|
111
|
+
|
|
112
|
+
handler = JSONAPI.configuration.authorization_scope
|
|
113
|
+
return scope unless handler
|
|
114
|
+
|
|
115
|
+
handler.call(controller: authorization_context, scope:, action: :index, model_class:)
|
|
100
116
|
end
|
|
101
117
|
|
|
102
118
|
def get_active_storage_records(current_record, association_name)
|
|
@@ -111,7 +127,8 @@ module JSONAPI
|
|
|
111
127
|
return if ctx.processed.include?(build_record_key(related_record))
|
|
112
128
|
|
|
113
129
|
requested = include_paths_to_relationship_names(ctx.all_includes, path_to_record)
|
|
114
|
-
serializer = self.class.new(related_record, parent_record:, association_name
|
|
130
|
+
serializer = self.class.new(related_record, parent_record:, association_name:,
|
|
131
|
+
authorization_context:,)
|
|
115
132
|
ctx.included_records << serializer.serialize_record(ctx.fields, requested_relationships: requested)
|
|
116
133
|
ctx.processed.add(build_record_key(related_record))
|
|
117
134
|
end
|
|
@@ -34,12 +34,14 @@ module JSONAPI
|
|
|
34
34
|
@jsonapi_object = nil
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def initialize(record, definition: nil, base_definition: nil, parent_record: nil, association_name: nil
|
|
37
|
+
def initialize(record, definition: nil, base_definition: nil, parent_record: nil, association_name: nil,
|
|
38
|
+
authorization_context: nil)
|
|
38
39
|
@record = record
|
|
39
40
|
@definition = definition || ResourceLoader.find_for_model(record.class)
|
|
40
41
|
@base_definition = base_definition
|
|
41
42
|
@parent_record = parent_record
|
|
42
43
|
@association_name = association_name
|
|
44
|
+
@authorization_context = authorization_context
|
|
43
45
|
@sti_subclass = nil
|
|
44
46
|
end
|
|
45
47
|
|
|
@@ -67,7 +69,7 @@ module JSONAPI
|
|
|
67
69
|
|
|
68
70
|
private
|
|
69
71
|
|
|
70
|
-
attr_reader :record, :definition, :parent_record, :association_name
|
|
72
|
+
attr_reader :record, :definition, :parent_record, :association_name, :authorization_context
|
|
71
73
|
|
|
72
74
|
def base_definition
|
|
73
75
|
@base_definition ||= definition
|
data/lib/json_api/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jpie
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Emil Kampp
|
|
@@ -88,6 +88,7 @@ files:
|
|
|
88
88
|
- ".claude/skills/nasa-power-of-ten-ruby/SKILL.md"
|
|
89
89
|
- ".claude/skills/root-cause-analysis/SKILL.md"
|
|
90
90
|
- ".claude/skills/skills-and-subagents/SKILL.md"
|
|
91
|
+
- ".claude/skills/writing-discipline/SKILL.md"
|
|
91
92
|
- ".cursor/agents/bias-reviewer.md"
|
|
92
93
|
- ".cursor/agents/lint-format.md"
|
|
93
94
|
- ".cursor/agents/nasa-power-of-ten-reviewer.md"
|
|
@@ -97,6 +98,7 @@ files:
|
|
|
97
98
|
- ".gitignore"
|
|
98
99
|
- ".rspec"
|
|
99
100
|
- ".rubocop.yml"
|
|
101
|
+
- CLAUDE.md
|
|
100
102
|
- Gemfile
|
|
101
103
|
- Gemfile.lock
|
|
102
104
|
- PERFORMANCE_BASELINE.md
|