w3c / json-ld-syntax

JSON-LD 1.1 Specification
https://w3c.github.io/json-ld-syntax/
Other
109 stars 38 forks source link

Introduce concept of "sealed” contexts #20

Closed gkellogg closed 5 years ago

gkellogg commented 6 years ago

A number of standards track specifications use JSON-LD for extensibility but intentionally place limitations on overriding the terms defined in a core context. For example:

Implementations may augment the provided @context with additional @context definitions but must not override or change the normative context.

https://www.w3.org/TR/activitystreams-core/#jsonld

Implementations MUST produce an error when an extension JSON-LD Context overrides the expanded URL for a term specified in the base JSON-LD Context (https://w3id.org/credentials/v1). To avoid the possibility of accidentally overriding terms, developers are urged to scope their extensions.

https://w3c.github.io/vc-data-model/#extensibility

It seems like it would be a nice feature to allow enforcement of this desire by JSON-LD processors. Then authors could be assured that the interpretation of a context would be proper and properly implemented JSON-LD processors would throw errors if rules were violated.

In short, I propose we add a keyword with boolean value such as "@sealed": true (that could appear in contexts) to JSON-LD 1.1 that enables processors to enforce a desire to prevent defined terms from being redefined in subsequent contexts, but allows for new terms (aka extensions) to be defined.

Original issue: Introduce concept of "sealed" contexts #656

ajs6f commented 5 years ago

@gkellogg This seems reasonable and useful to me.

Would sealing be a context-level-only feature? IOW, do you propose allowing some terms in a context to be sealed but not others?

simonstey commented 5 years ago

Would sealing be a context-level-only feature? IOW, do you propose allowing some terms in a context to be sealed but not others?

alternatively, one could also split the context into one sealed part and an unsealed one, and just import both right?

ajs6f commented 5 years ago

I imagine so, although the interweaving might be difficult... I'd have to work through some examples.

iherman commented 5 years ago

This issue was discussed in a meeting.

iherman commented 5 years ago

This issue was discussed in a meeting.

dlongley commented 5 years ago

Hello!

An idea was proposed at the meeting at TPAC that this issue could be addressed by simply ordering "extension" contexts first and "core" contexts last in an @context array. We've considered it and it doesn't work for a number of reasons.

First, there's the aesthetics of it (people would prefer a "core" @context to come first in the array) but there are also more serious technical problems. Here's one example:

http://tinyurl.com/ycrgkeyy

Here a SpecificCredential with a scoped context for the issuer property overrides the base definition for issuer with the extension -- causing evil/confusion. The issuer property MUST NOT be overridden, yet it is.

I think it would probably be best to create a "sealed"/"frozen" @context feature and, while we're at it, make it use the more "expected" order of precedence (for this feature). I think this feature is really essential for JSON-LD adoption as "the way" to do extensions in specs for open world data models.

BigBlueHat commented 5 years ago

@dlongley thanks for that example! Scoped contexts do introduce a whole new layer of complication/confusion/unexpectedness... That said, I'm not sure the current array ordering is that unintuitive/unexpected.

Developers (especially general Web developers) are very familiar with "cascading" thanks to CSS. Things currently work this way with JSON-LD @context values.

It's also the way JavaScript (ECMAScript)'s Object.assign() works--last one wins:

a = {'test': 'ing'};
b = {'test': 'er'};
console.log(Object.assign({}, a, b));
// Object { test: "er" }

And, it's also the way ES6's Object Rest/Spread Properties work:

a = {'test': 'ing'};
b = {'test': 'er'};
console.log({...a, ...b});

Consequently, I'd find flipping the order more confusing and intuitive--and out of keeping with the surrounding code one would write to create the local context. So, I'd be 👎 on flipping that order--especially between JSON-LD minor point releases. Sorry.

I'll leave the continued discussion around sealed contexts--especially as it relates to the scoped context example you gave for another time. 😃

dlongley commented 5 years ago

So, I'd be -1 on flipping that order--especially between JSON-LD minor point releases. Sorry.

To be clear, I wasn't suggesting we flip the order for term definitions, just that sealed contexts should apply left to right ("first sealed context wins"). I think it would be odd for them to apply right to left ("last sealed context wins").

iherman commented 5 years ago

Yep, I guess where we did make a mistake at TPAC is to think only the way context works in 1.0. I am a bit neutral about the problem of whether one type of ordering is more natural than the other; I can see the points of @BigBlueHat. However, as the example of @dlongley shows, the problem of scoped contexts shows the limits of this approach anyway, and makes the problem about right order possibly irrelevant... :-(

I.e., we may be back to the drawing board on that one.

BigBlueHat commented 5 years ago

@dlongley musing on this some more (as I work on Verifiable Claims Data Model tests), and I'm wondering how much of this is solely "scoped context" related.

For example, I altered the example you posted earlier, and made the VerifiableCredential definition use it's own (rather redundant looking) scoped context: http://tinyurl.com/ycldnsyv

      "VerifiableCredential": {
        "@id": "base:VerifiableCredential",
        "@context": {
          "issuer": {
            "@id": "base:issuer"
          }
        }
      }

That, consequently, "fixed" the problem (in this narrow scenario). 😉

So, what I'm wondering now is:

Thoughts?

dlongley commented 5 years ago

@BigBlueHat,

  • can this "sealing" be done now simply with more verbosity (however annoying)--as done above?
  • could that verbosity be removed by a new mechanism to express that "scoping on @type" is essentially prevented (or limited) on that particular context's terminology (i.e. VerifiableCredential can't have it's context's terms overridden)--perhaps that's automatic on the last, authoritative context.

Thoughts?

I suspect all of the requirements discussed in issue #98 likely can't be covered. Even so, I'm also a little apprehensive about creating contexts that may appear to have useless cruft in them -- instead using the clarity that a @seal feature would have.

It seemed like we arrived at a pretty good/coherent path forward for the @seal feature in #98.

azaroth42 commented 5 years ago

Some proposed content to be turned into specification text if it meets the use cases...

Thus, some examples...

{"@context": {"label": {"@id": "rdfs:label", "@sealed": true}}}

This context defines label to be rdfs:label, and any subsequent context that tries to define label will generate a processor error.


{"@context": {"@sealed": true, "label": "rdfs:label"}}

This is equivalent to the first example.


{"@context": {"label": {"@id": "rdfs:label", "@sealed": true}, 
    "value": {"@id": "rdf:value"}}}

Label is sealed, but value is not sealed.


{"@context": {"@sealed": true, "label": "rdfs:label", 
    "value": {"@sealed": false, "@id": "rdf:value"}}}

Equivalent to the previous, just in reverse


{"@context": {"sealed_data": {"@context": 
    {"@sealed": true, "label": "rdfs:label"}}}}

Within sealed_data, label is sealed to be rdfs:label, but can be redefined in contexts other than within sealed_data.


{"@context": {"sealed_data": {"@id": "rdf:value", "@sealed": true, 
    "@context": {"sealed_data": "eg:data"}}}}

An error, as sealed_data is still sealed. (?)


{"@context": {"wild_west": {"@id": "eg:playground", "@sealed": true, "@context": null}}}

You can't redefine wild_west because it is sealed to be eg:playground, but within the wild_west there is no defined context (it has been nulled out) and thus anything goes ... including redefining sealed terms. This should only work when the resetting and the sealing are in the same context.


{"@context": [
  {"sealed_data": {"@id": "rdf:value", "@sealed": true"},
  null,
  {"sealed_data": {"@id": "eg:playground"}
]}

Error state, as the null would remove a sealed term.


Questions arising:

(Tag @dlongley to take a look)

dlongley commented 5 years ago

I agree with Rob's examples.

Can you seal alias definitions, such that id being aliased to @id cannot be overridden? Propose that the answer is yes.

Yes.

Can you seal the default vocabulary definition via @vocab? Propose that the answer is no, it's only the definitions of terms that are sealed.

I think "no" makes more sense here, but I'm open to an argument for "yes".

Can you annotate a context with @sealed (c.f. #108) to seal it in your usage? Propose defer until #108 is resolved.

Also +1 to deferring.

Another example for clarity on wild_west:


{
  "@context": [
    {"wild_west": {"@id": "eg:playground", "@sealed": true, "@context": null}},
    {"wild_west": {"@context": "http://schema.org"}}
  ]
}

This is not an error and causes the scoped context for "wild_west" (anything nested under that term) to be "http://schema.org".


dlongley commented 5 years ago

Regarding this:


{"@context": {"sealed_data": {"@id": "rdf:value", "@sealed": true, 
    "@context": {"sealed_data": "eg:data"}}}}

An error, as sealed_data is still sealed. (?)


I'm not convinced that should be an error given that it's in the same document. This seems like something someone may want to do. I would expect the sealing here to prevent other documents from changing the scoped context.

azaroth42 commented 5 years ago

I think we need a separate issue for the partial redefinition case for adding a context to wild_west. Will create one.

iherman commented 5 years ago

This issue was discussed in a meeting.

iherman commented 5 years ago
{
   "@context": {
       "sealed_data": {
           "@id": "rdf:value",
           "@sealed": true,
           "@context": {
               "sealed_data": "eg:data"
           }
       }
   }
}

An error, as sealed_data is still sealed. (?)

I would agree this is a an error; I am not sure I understand @dlongley's remark "I'm not convinced that should be an error given that it's in the same document.". More exactly, how would one define this exception in a spec?

gkellogg commented 5 years ago

I'm not sure it's an error either, as the top-level sealed_data is sealed, and part of what's sealed is hat it introduces a new context. I think it effectively changes the interpretation of sealed_data (or whatever else is defined) under the first use of sealed_data without unsealing anything.

The only thing that unseals is to have a scoped context include null, so for example:

{
   "@context": {
       "sealed_data": {
           "@id": "rdf:value",
           "@sealed": true,
           "@context": [null, {"sealed_data": "eg:data"}]
       }
   }
}

both unseals and introduces a new term definition. (altho, eg cannot then be defined as a term, so would look like an IRI scheme`).

dlongley commented 5 years ago

I'm not sure it's an error either, as the top-level sealed_data is sealed, and part of what's sealed is hat it introduces a new context. I think it effectively changes the interpretation of sealed_data (or whatever else is defined) under the first use of sealed_data without unsealing anything.

Yes, this was my interpretation as well. And it seems like it enables more use cases. The scoped context is part of the sealed definition and it isn't null (which would unseal it). Whatever is in that @context applies even if it means providing a scoped term definition for the same term.

gkellogg commented 5 years ago

Interesting corner case: what if two sealed contexts are used, and a term in one of them contains a scoped context which includes null. It probably shouldn't be able to remove all contexts, so this would just be ignored. For example:

{
  "@context": [
    {"term1": {"@id": "http://example.com/term1", "@sealed": true}},
    {"term2": {"@id": "http://example.com/term2", "@sealed": true, {"@context": null}}
  ],
  "term2": {
    "term1": "This should still evaluate to http://example.com/term1",
    "term2": "This may still evaluate to http://example.com/term2 if the @context: null above was ignored"
  }
}

The problem is, how to detect this? The simplest implementation is to seal terms when they include @sealed or their contexts includes @sealed and prevent (with a warning) any attempt to change it later. When setting a new context, we can prohibit this if the active context contains any sealed terms, unless setting it to null (or something starting with null) if it comes from a scoped context of a sealed term. I'm not sure how to do this when multiple contexts are involved.

azaroth42 commented 5 years ago

I'd like to iron out the cases that do NOT have @context:null first. Then we can look at unsetting.

For the processing, is the sealing before or after processing scoped contexts? If it's after, then the sealed_data example works (in my head) as expected by @dlongley and @gkellogg. If it happens before then it works (in my head) as expected by myself and @iherman. Is this the correct reasoning?

pchampin commented 5 years ago

I'm not sure I would express this in terms of "before / after", but I agree with @gkellogg 's argument: "the top-level sealed_data is sealed, and part of what's sealed is that it introduces a new context".

iherman commented 5 years ago

@azaroth42 you will have to explain this a bit... you mean whether sealing happens before or after the setting of the @id is done (in our example)?

azaroth42 commented 5 years ago

When a processor encounters the term definition, it has a choice of whether to process @sealed first or @context first. If it processes @context first, then it descends into the scoped context and processes the terms there (which might in turn have scoped contexts, and sealing) before processing the sealing.

In the example, my understanding is thus that sealed_data at the top level would not be sealed if @context is processed before @sealed.

pchampin commented 5 years ago

Sorry, this is still very abstract for me. I went back to the expansion algorithm in the current draft.

EDITED: I was mistaken on the different steps. Replaced "Step 7.1" by "Step 9.5" above. I'm actually unsure about how 7.1 should handle this...

gkellogg commented 5 years ago

@azaroth42 asks:

For the processing, is the sealing before or after processing scoped contexts?

As @pchampin said, I believe the sealing is done in the term definition phase. Any term, sealed or unsealed, may define a scoped context, it's only when it comes into play during expansion that it might come into conflict (warning, not error IMO) if used to redefine a sealed term.

I have it implement, but not yet tested, and the changes are fairly localized:

I'll see if I can get spec text and some tests added before tomorrow's call.

dlongley commented 5 years ago

@gkellogg,

Interesting corner case: what if two sealed contexts are used, and a term in one of them contains a scoped context which includes null. It probably shouldn't be able to remove all contexts, so this would just be ignored.

Apologies to @azaroth42 for continuing down this path, but in thinking about your corner-case...

It seems like, since the original sealed context did not define term2 at all, there would be no expectation for what might appear underneath that term. Using sealed contexts is primarily (exclusively?) tied to making JSON-LD more compatible with JSON-only processors that rely on tree structures. This means that no such software that is relying on the first sealed context would ever traverse into term2 (as it is not defined). So term2 should be free to clear what is underneath it.

It may be that specifying a scoped context of @context: null should always be acceptable in new term definitions. If term2 were not new (i.e. it was defined and sealed by the first context), then its definition would be ignored as expected.

gkellogg commented 5 years ago

@dlongley said:

This means that no such software that is relying on the first sealed context would ever traverse into term2 (as it is not defined). So term2 should be free to clear what is underneath it.

The implication is that, when traversing into an unsealed term, the active context is cloned and all term definitions are unsealed. This could work, but it seems it will have a potentially big impact on memory and performance. Perhaps there's away to parameterize the expansion algorithm invocation, to cause all every subsequent attempt to update the context to look like it came from a sealed term.

It may be that specifying a scoped context of @context: null

That would fall out of the previous logic, as we don't actually check for setting the context until expanding.

iherman commented 5 years ago

Just for my understanding:

{
   "@context": {
       "sealed_data": {
           "@id": "rdf:value",
           "@sealed": true,
           "@context": {
               "sealed_data": "eg:data"
           }
       }
   },
   "sealed_data" {
       ...
       "sealed_data" {
           ...
       }
   }
}

the first appearance of "sealed_data" (on the top level) would expand into "rdf:value" while the second appearance would become "eg:data". Actually, I presume this is unrelated to sealing: this would be valid without "@sealed", too.

However

{
   "@context": [{
       "sealed_data": {
           "@id": "rdf:value",
           "@sealed": true,
           "@context": {
               "sealed_data": "eg:data"
           }
       }
   }, {
       "sealed_data" : {
           "@id" : "eg:something_else"
       }
   }]
}

would be an error, because the sealing is switched on after all the embedded contexts are processed.

Is this correct?

dlongley commented 5 years ago

In thinking more about your "corner-case", @gkellogg, I think it helps highlight more about what we're trying to do with this feature.

This new sealed feature is intended to enable processor-enforcement of fixed semantics in JSON(-LD) of the sort typically only described in specifications. Specifications that use JSON and intend to allow for extensibility describe a set of terms with fixed semantics that must not change unless:

  1. The spec describes that they have different semantics when they appear at a different nesting level in the JSON tree, i.e. a term definition changes in a specified way based on a different "scope". For example:
{
  "sealed1": {
    "sealed2": {
      "sealed1": "this sealed1 has a new meaning"
    }
  }
}

This is what @iherman's example is about above.

  1. The spec indicates that an extension term (a term to be described by another specification or an application-specific term) may appear in the JSON structure and it may have any terms with any definitions underneath it, aka "scoped within it".

Common patterns for extensibility here include:

  1. Calling out a specific term (that is defined in the core spec) underneath which any new terms may be defined:
{
  "sealed1": "foo",
  "sealed2": {
    "sealed3": "bar"
  },
  "sealed4WhereExtensionsGo": { /* anything */ }
}

This is the sort of pattern for which defining a specific @sealed term with a scoped @context: null would apply.

  1. Or allowing any new term (that is not mentioned at all in the core spec) to provide its own definition and, optionally, define its own scoped context:
{
  "sealed1": "foo",
  "sealed2": {
    "sealed3": "bar",
    "extension1": "baz",
    "extension2": {
      "extension3": "moo",
      "extension4": { /* anything */ }
    }
  },
  "extension5": "woof",
  "extension6": { /* anything */ }
}

The latter applies to your "corner-case", which I don't think is so much in a corner anymore, but rather quite common. This hints that we should treat any previously undefined terms as if they had been specified with a scoped @context: null by default. This hints at a rule that terms should "own" their own scopes. This means that any new terms (that were previously completely undefined) should be able to define whatever they want in a scoped context. This rule would only apply to nesting, however -- not "type-based scoping" because it leads to this problem.

dlongley commented 5 years ago

@iherman,

Is this correct?

Yes, I agree with everything you said above.

gkellogg commented 5 years ago

@iherman i believe both cases work the same; not, “errors”, per se, but perhaps a warning, and processing is aborted. As written, the only way to redefine a sealer term is to clear out the context. In your first example, the scoped context is handled during expansion and looks like an attempt to redefine the term, so is ignored. The second case does the same, but not during the expansion process.

gkellogg commented 5 years ago

@dlongley to treat undefined terms (or unsealed defined terms?) as if the context is wiped out underneathwout be a major departure from current behavior, and would yield unexpected results. I would say, instead, as we discussed earlier, that under properties that are. It sealed, previously sealed terms are effectively unsealed, but their definitions remain, including any scoped contexts that may define sealed terms.

iherman commented 5 years ago

Do I detect a contradiction between the answer of @dlongley and @gkellogg here?

@dlongley agreed with what I said. Ie, just to make it clear, this means

{
   "@context": {
       "sealed_data": {
           "@id": "rdf:value",
           "@sealed": true,
           "@context": {
               "sealed_data": "eg:data"
           }
       }
   },
   "sealed_data" {
       ...
       "sealed_data" {
           ...
       }
   }
}

is fine. However, @gkellogg seems to say this is an error/warning. Which is it? Or more exactly, how should our spec go, ie, should this be correct or not correct?

gkellogg commented 5 years ago

I created test cases and spec text based on my understanding of our discussions that the only way to redefine a term is to clear out the context, something that can only be done from a scoped context within a sealed term.

Note that scoped contexts are not processed when they are defined, but when they are encountered during expansion, as if they had been specified inline.

If we want to do something different, we could say that scoped contexts coming from sealed terms can redefine sealed terms, but IIRC, we hadn’t discussed that.

iherman commented 5 years ago

Sorry to be a drag, @gkellogg, but it is very difficult to understand the spec text as included in the API. Would it be possible to have a draft that would appear in the syntax document (that is what an end-user, like your truly, would read...)

dlongley commented 5 years ago

@gkellogg,

...to treat undefined terms (or unsealed defined terms?) as if the context is wiped out underneathwout be a major departure from current behavior, and would yield unexpected results.

Hmm, I didn't mean to suggest that. So I shouldn't have said we'd treat them as if the scoped context was @context: null by default. Rather, what I meant by that was that a new term should be able to redefine whatever it wants via a scoped context. The rule I think I'm suggesting is that terms always "own" their own nested scopes. This rule would only apply to nesting, however -- not "type-based scoping" because it leads to this problem.

dlongley commented 5 years ago

Perhaps the "type-scoping" difference (vs. nesting) I mention above could be remedied by sealing type definitions in a manner similar to what @BigBlueHat did here: https://github.com/w3c/json-ld-syntax/issues/20#issuecomment-454485321

iherman commented 5 years ago

This issue was discussed in a meeting.

BigBlueHat commented 5 years ago

On the "bikeshedding" front, we may want to consider the term "frozen" in place of "sealed." From MDN:

Existing properties in objects frozen with Object.freeze() are made immutable. Objects sealed with Object.seal() can have their existing properties changed. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal#Comparison_to_Object.freeze()

I've not done a wider survey of other languages yet, but as JSON's next-of-kin is JavaScript, it seems prudent to consider naming that matches there as closely as possible.

pchampin commented 5 years ago

That's a good point; I agree that terminology is important.

That being said, I like the metaphor of the seal, as I have used it extensively in explaining how the processing should be done. I can't find an equivalent with a "frozen" metaphor.

[[failed attempt to make a pathetic pun about seals, see ice and freezing...]]

gkellogg commented 5 years ago

Maybe allow 10 minutes for bikeshedding on the call tomorrow. I can go either way.

iherman commented 5 years ago

This issue was discussed in a meeting.

tcole3 commented 5 years ago

Following up on the question @iherman raised at the end of yesterday's discussion, the need for a json-ld author to redefine select schema.org terms is real - it will create more work (or confusion for simple json developers) if there is no easy way to override a decision by schema.org to seal their context - e.g., could lead authors to clone and maintain their own variants of schema.org context.

Illustration -- As has come up in the WG previously, schema.org has many properties with a range that encompasses multiple data types, e.g., per current schema.org documentation both Text and URL are listed as values expected for the properties genre, artMedium, artworkSurface, artform, fileFormat. But the schema.org context specifies only URL (@id) when defining each of these terms, e.g. from the current schema.org context document:

"fileFormat": { "@id": "schema:fileFormat", "@type": "@id" }

So, in one or our applications here at Illinois we routinely reference schema.org context document and then redefine these 5 terms, e.g. (for fileFormat):

     "@context": [
        "http://schema.org/",
        {
            "s": "http://schema.org/",
            "fileFormat": {  "@id": "s:fileFormat",  "@type": "s:Text"  }
        } ] 

For full example (we have about 4,500 of these), see: http://imagesearch-test1.library.illinois.edu/jsonld/10189v2.json

Current JSON-LD playgrounds (both) accept these redefinitions and understands our use of text strings as values for these properties. So the following line in our json-ld instance

"fileFormat": "image/jpg"

is expanded by the playgrounds as we want:

        "http://schema.org/fileFormat": [
          {
            "@type": "http://schema.org/Text",
            "@value": "image/jpg"
          }   ],

If we fail to redefine these schema.org terms -- or if in the future our attempt in local context to redefine these terms are ignored because schema.org someday chooses to seal their context, then the playgrounds turn our strings into relative URLs. A version of our file without the redefinitions is here: http://imagesearch-test1.library.illinois.edu/jsonld/10189v3.json

In this case (no redefinition) the same key-value in the instance as above:

"fileFormat": "image/jpg"

is expanded by the playgrounds this way (NOT the way we want):

        "http://schema.org/fileFormat": [
          {
            "@id": "https://json-ld.org/playground/image/jpg"
          }   ],

Of course we can effectively work around the default term definitions on a case by case basis by using object values for the un-redefined properties and explicitly specifying @value and @type:s:Text ourselves (will this technique still work if term definition is sealed?).

But this is not the ideal solution to prescribe (especially for simple json developers) and notably the Google SDTT does not accept this usage (one of a few issues with the tool which I don't think actually looks at context at all).

So, personally I would appreciate a more flexible seal mechanism that allowed some kind of a seal override on any externally referenced context document that includes the @sealed:true directive.

iherman commented 5 years ago

The problem is real (as I said on the call, we do something similar for Web Publication Manifests). But I am not sure what that would mean...

  1. We could revive the approach, briefly mentioned at some point but not really retained, to be able to "seal" only specific terms or those terms that are explicitly mentioned. In the schema.org example, it would mean sealing the @id value (and possibly other values as given in the schema.org in the current context file) but allow extending the term definitions like what @tcole3 has shown. The problem was that this goes against the approach in JSON-LD 1.0 (where redefinition is an all or nothing action). Specifying this properly may lead to a spaghetti specification (and implementation...)

  2. Another, more pragmatic approach is to make it very clear that... if possible, you should not seal a context. To be more specific, make it very clear that sealing an under-specified context may lead major issues, and publishers shouldn't do that. Sealing should be reserved for very specific use cases, where the context is extremely well specified and it would be an issue if they were redefined.

    Schema.org is such an under-specified context (intentionally so), i.e., it would create lots of issues if it was sealed (truth must be said, I do not think they expressed interest in this). This also means that we should refrain using schema.org in any of our examples around sealing (@pchampin, this may require a slight re-write of #119). I think the same is true for FOAF and Dublin Core, b.t.w. At this moment, the VC ontology might be the only one coming to my mind that does require this. (@azaroth42, @tcole3, I am not sure the annotation vocabulary should be sealed either, but I am not sure).

gkellogg commented 5 years ago
  1. We could revive the approach, briefly mentioned at some point but not really retained, to be able to "seal" only specific terms or those terms that are explicitly mentioned. In the schema.org example, it would mean sealing the @id value (and possibly other values as given in the schema.org in the current context file) but allow extending the term definitions like what @tcole3 has shown. The problem was that this goes against the approach in JSON-LD 1.0 (where redefinition is an all or nothing action). Specifying this properly may lead to a spaghetti specification (and implementation...)

We need to consider the primary use case for sealing terms/contexts, which is to allow naive JSON apps to be able to interpret values as defined in a spec; this includes how to treat string values, and if an object value should be treated as a list, a map, or whatever. Allowing these things (or anything, really) to be overridden on a term sort of by definition does not allow naive apps to be able to properly understand their values. The only possible exception would be to add @container: @set to ensure that compaction always uses array notation, but that's a compaction use case, which does not relate to naive JSON apps. So, I don't see a reason for us to do this.

  1. Another, more pragmatic approach is to make it very clear that... if possible, you should not seal a context. To be more specific, make it very clear that sealing an under-specified context may lead major issues, and publishers shouldn't do that. Sealing should be reserved for very specific use cases, where the context is extremely well specified and it would be an issue if they were redefined.

Yes, absolutely; we should caution that this feature should be used judiciously, if at all.

pchampin commented 5 years ago

I lean towards option 2. Sealing should only be used in specific use cases, and schema.org does not fit in those, I think.

On Sun 3 Feb 2019, 21:04 Gregg Kellogg <notifications@github.com wrote:

  1. We could revive the approach, briefly mentioned at some point but not really retained, to be able to "seal" only specific terms or those terms that are explicitly mentioned. In the schema.org example, it would mean sealing the @id value (and possibly other values as given in the schema.org in the current context file) but allow extending the term definitions like what @tcole3 https://github.com/tcole3 has shown. The problem was that this goes against the approach in JSON-LD 1.0 (where redefinition is an all or nothing action). Specifying this properly may lead to a spaghetti specification (and implementation...)

We need to consider the primary use case for sealing terms/contexts, which is to allow naive JSON apps to be able to interpret values as defined in a spec; this includes how to treat string values, and if an object value should be treated as a list, a map, or whatever. Allowing these things (or anything, really) to be overridden on a term sort of by definition does not allow naive apps to be able to properly understand their values. The only possible exception would be to add @container: @set to ensure that compaction always uses array notation, but that's a compaction use case, which does not relate to naive JSON apps. So, I don't see a reason for us to do this.

  1. Another, more pragmatic approach is to make it very clear that... if possible, you should not seal a context. To be more specific, make it very clear that sealing an under-specified context may lead major issues, and publishers shouldn't do that. Sealing should be reserved for very specific use cases, where the context is extremely well specified and it would be an issue if they were redefined.

Yes, absolutely; we should caution that this feature should be used judiciously, if at all.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/w3c/json-ld-syntax/issues/20#issuecomment-460083446, or mute the thread https://github.com/notifications/unsubscribe-auth/AASl5DXM2y0LdKUGCuFr0bJH9sUxZ8YXks5vJ0DagaJpZM4U-BsL .

ajs6f commented 5 years ago

Agreed. The risks associated with misinterpreting schema.org data seem very small in comparison with the risks of misinterpreting WoT or Verifiable Claims data.

iherman commented 5 years ago

This issue was discussed in a meeting.

iherman commented 5 years ago

This issue was discussed in a meeting.