## Turtle Start ##
@prefix schema:    <http://schema.org/> .
@prefix xsd:       <http://www.w3.org/2001/XMLSchema#> .
@prefix rdfs:      <http://www.w3.org/2000/01/rdf-schema#> .
@prefix wdrs:      <http://www.w3.org/2007/05/powder-s#> .
@prefix foaf:      <http://xmlns.com/foaf/0.1/> .
@prefix acl:       <http://www.w3.org/ns/auth/acl#> .
@prefix filter:    <http://www.openlinksw.com/schemas/acl/filter#> .
@prefix oplacl:    <http://www.openlinksw.com/ontology/acl#> .
@prefix oplres:    <http://www.openlinksw.com/ontology/restrictions#> .
@prefix oplofr:    <http://www.openlinksw.com/ontology/offers#> .
@prefix source:    <http://virtuoso.openlinksw.com/data/turtle/Offers-authorizatoins-and-restrictions.ttl> .

# --- Document Metadata ---

source: a schema:CreativeWork ;
    schema:name "OPAL, Graph, and File Access Authorization, Groups and Restrictions Definitions" ;
    schema:comment "This document describes the rules, groups and restrictions required for the OPAL and graph access offers." ;
    schema:author <http://www.openlinksw.com/#this> ;
    schema:datePublished "2026-01-14T00:00:00Z"^^xsd:dateTime .

# --- Offer Groups ---

<http://data.openlinksw.com/oplweb/OfferGroupChatService#this> a oplofr:OfferGroup ;
    schema:name "OPAL Chat Service Offers" ;
    rdfs:label "OPAL Chat Service Offers" .

<http://data.openlinksw.com/oplweb/OfferGroupApiAccess#this> a oplofr:OfferGroup ;
    schema:name "OPAL API Access Offers" ;
    rdfs:label "OPAL API Access Offers" ;
    schema:description "Offers for sessions instantiated via the /chat/api endpoints." .

<http://data.openlinksw.com/oplweb/OfferGroupGraphAccess#this> a oplofr:OfferGroup ;
    schema:name "Specific Knowledge Graph Access Offers" ;
    rdfs:label "Specific Knowledge Graph Access Offers" .

<http://data.openlinksw.com/oplweb/OfferGroupFileAccess#this> a oplofr:OfferGroup ;
    schema:name "Specific Knowledge File Access Offers" ;
    rdfs:label "Specific Knowledge File Access Offers" .

## --- Opal Chat Access ---
# ==============================================================================
# Conditonal Group Definitions for each offer type
# ==============================================================================

<http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:DataTwinglerSpecificModuleEntryLevelOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:DataTwinglerSpecificModulePlusOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:DataTwinglerSpecificModuleProOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:DataTwinglerSpecificModuleMaxOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:SupportAssistantSpecificModuleEntryLevelOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) . }"
     ] .

<http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:SupportAssistantSpecificModulePlusOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Data Twingler Assistant offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:SupportAssistantSpecificModuleProOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased access to the Support Assistant chat offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:SupportAssistantSpecificModuleMaxOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Entry level offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:BringYourOwnKeyEntryLevelOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Plus level offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:BringYourOwnKeyPlusOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) . filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/BringYourOwnKeyProUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Pro level offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:BringYourOwnKeyProOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) . filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/MaxUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "OPAL Users identified using a NetID based Identifier who have purchased the Max level offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:MaxOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) . filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

# ==============================================================================
# Restrictions
# ==============================================================================

# ------------------------------------------------------------------------------
# A. Session & Token Limits
# ------------------------------------------------------------------------------

# --- Entry Level Limits ---

# Max Prompts per session : 20
# Max Input Tokens per prompt: 2,000
# Max Total Tokens per session: 4,000
# Rate limit per hour: 1500 (25 per minute)

oplres:max-prompt-count-per-session a oplres:Restriction ;
  schema:name "Max prompts per session" ;
  schema:description "Users are limited to a maximum of 20 prompts within a single session" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
  oplres:hasMaxValue "20"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-token-usage-per-prompt a oplres:Restriction ;
  schema:name "Max tokens per prompt" ;
  schema:description "Each prompt can use up to 2000 tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
  oplres:hasMaxValue "2000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-total-token-usage-per-session a oplres:Restriction ;
  schema:name "Max total tokens per session" ;
  schema:description "The total token usage for an entire session is capped at 4000 tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
  oplres:hasMaxValue "4000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-prompt-interval-count-entry a oplres:Restriction ;
  schema:name "Max 25 prompts for min" ;
  schema:description "Up to 25 prompts" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
  oplres:hasMaxValue "1500"^^xsd:int ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  wdrs:describedby <#source> .


### Average prompts for interval of 1h

oplres:max-prompt-interval-1h a oplres:Restriction ;
  schema:name "Interval of 1 hour" ;
  schema:description "Interval used for all limits" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval> ;
  oplres:hasMaxValue "3600"^^xsd:int ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgentClass foaf:Agent ;
  wdrs:describedby <#source> .

# --- Plus Level Limits ---

# Max Prompts per session: 200
# Max Input Tokens per prompt: 20,000
# Max Total Tokens per session: 40,000
# Rate limit per hour: 15000 (250 per minute)

oplres:max-prompt-count-per-session-plus-offer a oplres:Restriction ;
  schema:name "Max prompts per session" ;
  schema:description "Users are limited to a maximum of 200 prompts within a single session" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
  oplres:hasMaxValue "200"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-token-usage-per-prompti-plus-offer a oplres:Restriction ;
  schema:name "Max tokens per prompt" ;
  schema:description "Each prompt can use up to 20000 tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
  oplres:hasMaxValue "20000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-total-token-usage-per-session-plus-offer a oplres:Restriction ;
  schema:name "Max total tokens per session" ;
  schema:description "The total token usage for an entire session is capped at 40000 tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
  oplres:hasMaxValue "40000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-prompt-interval-count-plus a oplres:Restriction ;
  schema:name "Max 250 prompts for interval 1 min" ;
  schema:description "Up to 250 prompts" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
  oplres:hasMaxValue "15000"^^xsd:int ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  wdrs:describedby <#source> .

# --- Pro Level Limits ---

# Max Prompts: 400
# Max Input Tokens: 100,000
# Max Total Tokens: 200,000
# Rate limit per hour: 30000 (500 per minute)

oplres:max-prompt-count-per-session-pro-offer a oplres:Restriction ;
  schema:name "Max prompts per session" ;
  schema:description "Users are limited to a maximum of 400 prompts within a single session" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
  oplres:hasMaxValue "400"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyProUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-token-usage-per-prompt-pro-offer a oplres:Restriction ;
  schema:name "Max tokens per prompt" ;
  schema:description "Each prompt can use up to 100k tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
  oplres:hasMaxValue "100000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyProUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-total-token-usage-per-session-pro-offer a oplres:Restriction ;
  schema:name "Max total tokens per session" ;
  schema:description "The total token usage for an entire session is capped at 200k tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
  oplres:hasMaxValue "200000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyProUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-prompt-interval-count-pro a oplres:Restriction ;
  schema:name "Max 500 prompts for interval 1 min" ;
  schema:description "Up to 500 prompts" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
  oplres:hasMaxValue "3000"^^xsd:int ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyProUsers#this> ;
  wdrs:describedby <#source> .

# --- Max Level Limits ---

# Max Prompts per session: 1,000
# Max Input Tokens per prompt: 500,000
# Max Total Tokens per session: 1,000,000
# Rate limit per hour: 60000 (1000 per minute)
oplres:max-prompt-count-per-session-max-offer a oplres:Restriction ;
  schema:name "Max prompts per session" ;
  schema:description "Users are limited to a maximum of 1k prompts within a single session" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
  oplres:hasMaxValue "1000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/MaxUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-token-usage-per-prompt-max-offer a oplres:Restriction ;
  schema:name "Max tokens per prompt" ;
  schema:description "Each prompt can use up to 500k tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
  oplres:hasMaxValue "500000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/MaxUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-total-token-usage-per-session-max-offer a oplres:Restriction ;
  schema:name "Max total tokens per session" ;
  schema:description "The total token usage for an entire session is capped at 1M tokens" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
  oplres:hasMaxValue "1000000"^^xsd:decimal ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/MaxUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:max-prompt-interval-count-max a oplres:Restriction ;
  schema:name "Max 1000 prompts for interval 1 min" ;
  schema:description "Up to 1000 prompts" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
  oplres:hasMaxValue "60000"^^xsd:int ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/MaxUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .


# ------------------------------------------------------------------------------
# Module & Tool Restrictions
# ------------------------------------------------------------------------------

oplres:use-data-twingler a oplres:Restriction ;
  schema:name "Session Scoped to Data Twingler module" ;
  schema:description "OPAL Sessions that use the Data Twingler module" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:module> ;  
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasRestrictedValue "data-twingler-config"^^xsd:string ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

oplres:use-support-assistant a oplres:Restriction ;
  schema:name "Session Scoped to the Support Assistant" ;
  schema:description "OPAL Sessions that use the Support Assistant" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:module> ;  
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasRestrictedValue "virtuoso-support-assistant-config"^^xsd:string ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .

# --- Requiring a value ---

# --- Entry Level Features ---

oplres:entry-level-assistant-access a oplres:Restriction ;
  schema:name "Entry Level assistant access" ;
  schema:description "Entry Level assistant access" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter	 <urn:oai:chat:module> ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  oplres:hasRestrictedValue "cello-config,data-twingler-config,opml-rss-news-reader,uda-support-assistant-config,virtuoso-support-assistant-config,data-twingler-uniprot" ;
  wdrs:describedby <#source> .

oplres:entry-level-assistant-access-tools a oplres:Restriction ;
  schema:name "Entry Level assistant access for tools" ;
  schema:description "Entry Level assistant access to the tools" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter	 <urn:oai:chat:enabled-tools> ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  oplres:hasRestrictedValue "UB.DBA.sparqlQuery,Demo.demo.execute_spasql_query,Demo.demo.execute_sql_query" ;
  oplres:hasMaxValue 1 ;
  wdrs:describedby <#source> .

# --- Plus Level Features ---

oplres:plus-level-assistant-access a oplres:Restriction ;
  schema:name "Plus assistant access" ;
  schema:description "Plus assistant access" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter	 <urn:oai:chat:module> ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  oplres:hasRestrictedValue "cello-config,data-twingler-config,opml-rss-news-reader,uda-support-assistant-config,virtuoso-support-assistant-config,data-twingler-uniprot" ;
  wdrs:describedby <#source> .

oplres:plus-level-assistant-access-tools a oplres:Restriction ;
  schema:name "Plus assistant access for tools" ;
  schema:description "Plus assistant access to the tools" ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter	 <urn:oai:chat:enabled-tools> ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  oplres:hasRestrictedValue "UB.DBA.sparqlQuery,Demo.demo.execute_spasql_query,Demo.demo.execute_sql_query,OAI.DBA.WEB_FETCH,OAI.DBA.SPONGE_URL,FCT.DBA.FacetSearch" ;
  oplres:hasMaxValue 2 ;
  wdrs:describedby <#source> .

# --- Pro Level Features ---

# --- Max Level Features ---

oplres:restrict-enable-api-keys a oplres:Restriction ;
  schema:name "Enable system-wide API key" ;
  schema:description "Allow use of system-wide API key." ;
  oplres:hasRestrictedResource <urn:oai:chat> ;
  oplres:hasRestrictedParameter <urn:oai:chat:enable-api-keys> ;
  oplres:hasRealm oplacl:DefaultRealm ;
  oplres:hasRestrictedValue "1"^^xsd:string ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/MaxUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  oplres:hasAgent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  wdrs:describedby <#source> .



# ==============================================================================
# Rules
# ==============================================================================

# --- Chat access rule ---

oplacl:chat-access-offers a acl:Authorization ;
  schema:name "Rule to allow access to /chat when an offer is purchased" ;
  acl:accessTo <urn:oai:chat> ;
  oplacl:hasAccessMode oplacl:Read, oplacl:Write ;
  acl:agent <http://data.openlinksw.com/oplweb/group/DataTwinglerEntryLevelSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/DataTwinglerPlusSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/DataTwinglerProSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/DataTwinglerMaxSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/SupportAssistantEntryLevelSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/SupportAssistantPlusSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/SupportAssistantProSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/SupportAssistantMaxSpecificChatUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyEntryLevelUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyPlusUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/BringYourOwnKeyProUsers#this> ;
  acl:agent <http://data.openlinksw.com/oplweb/group/MaxUsers#this> ;
  oplacl:hasRealm oplacl:DefaultRealm ;
  oplacl:hasScope oplacl:Query .


## --- OPAL Chat API Access
# ==============================================================================
# Conditional Group Definitions for each offer type
# ==============================================================================

<http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> a oplacl:ConditionalGroup ;
    foaf:name "Users with API Access Entry Level License" ;
    oplacl:hasCondition [
      a oplacl:GroupCondition, oplacl:QueryCondition ;
      oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:ApiAccessEntryLevelOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> a oplacl:ConditionalGroup ;
    foaf:name "Users with API Access Medium Level License" ;
    oplacl:hasCondition [
      a oplacl:GroupCondition, oplacl:QueryCondition ;
      oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:ApiAccessMediumLevelOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> a oplacl:ConditionalGroup ;
    foaf:name "Users with API Access Advanced Level License" ;
    oplacl:hasCondition [
      a oplacl:GroupCondition, oplacl:QueryCondition ;
      oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:ApiAccessAdvancedLevelOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> a oplacl:ConditionalGroup ;
    foaf:name "Users with API Access Max License" ;
    oplacl:hasCondition [
      a oplacl:GroupCondition, oplacl:QueryCondition ;
      oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:ApiAccessMaxOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) .  filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

# ==============================================================================
# Restrictions
# ==============================================================================

# ------------------------------------------------------------------------------
# Session & Token Limits
# ------------------------------------------------------------------------------

# --- Entry Level Limits ---

# Max Prompt per session: 20
# Max Input Tokens per prompt: 2,000
# Max Total Tokens per session: 4,000
# Rate limit per hour: 1500 (25 per minute)

oplres:api-entry-max-prompts a oplres:Restriction ;
    schema:name "API Entry: Max prompts per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "20"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> .

oplres:api-entry-max-input-tokens a oplres:Restriction ;
    schema:name "API Entry: Max input tokens per prompt" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "2000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> .

oplres:api-entry-max-total-tokens a oplres:Restriction ;
    schema:name "API Entry: Max total tokens per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "4000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> .

oplres:api-entry-rate-limit a oplres:Restriction ;
    schema:name "API Entry: Max prompts per minute" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "1500"^^xsd:int ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> .

# --- Medium Level Limits ---

# Max Prompts per session: 200
# Max Input Tokens per prompt: 20,000
# Max Total Tokens per session: 40,000
# Rate limit per hour: 15000 (250 per minute)

oplres:api-medium-max-prompts a oplres:Restriction ;
    schema:name "API Medium: Max prompts per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "200"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> .

oplres:api-medium-max-input-tokens a oplres:Restriction ;
    schema:name "API Medium: Max input tokens per prompt" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "20000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> .

oplres:api-medium-max-total-tokens a oplres:Restriction ;
    schema:name "API Medium: Max total tokens per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "40000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> .

oplres:api-medium-rate-limit a oplres:Restriction ;
    schema:name "API Medium: Max prompts per minute" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "15000"^^xsd:int ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> .

# --- Advanced Level Limits ---

# Max Prompts: 400
# Max Input Tokens: 100,000
# Max Total Tokens: 200,000
# Rate limit per hour: 30000 (500 per minute)

oplres:api-advanced-max-prompts a oplres:Restriction ;
    schema:name "API Advanced: Max prompts per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "400"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> .

oplres:api-advanced-max-input-tokens a oplres:Restriction ;
    schema:name "API Advanced: Max input tokens per prompt" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "100000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> .

oplres:api-advanced-max-total-tokens a oplres:Restriction ;
    schema:name "API Advanced: Max total tokens per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "200000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> .

oplres:api-advanced-rate-limit a oplres:Restriction ;
    schema:name "API Advanced: Max prompts per minute" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "30000"^^xsd:int ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> .

# --- Max Level Limits ---

# Max Prompts per session: 1,000
# Max Input Tokens per prompt: 500,000
# Max Total Tokens per session: 1,000,000
# Rate limit per hour: 60000 (1000 per minute)

oplres:api-max-max-prompts a oplres:Restriction ;
    schema:name "API Max: Max prompts per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "1000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> .

oplres:api-max-max-input-tokens a oplres:Restriction ;
    schema:name "API Max: Max input tokens per prompt" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompt-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "500000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> .

oplres:api-max-max-total-tokens a oplres:Restriction ;
    schema:name "API Max: Max total tokens per session" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-tokens> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "1000000"^^xsd:decimal ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> .

oplres:api-max-rate-limit a oplres:Restriction ;
    schema:name "API Max: Max prompts per minute" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:max-prompts-interval-count> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasMaxValue "60000"^^xsd:int ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> .

# ------------------------------------------------------------------------------
# Feature & Tool Restrictions
# ------------------------------------------------------------------------------

# --- Entry Level Features ---

# SQL, SPASQL, Remote SPARQL, GraphQL

oplres:api-entry-tools a oplres:Restriction ;
    schema:name "API Entry: Included Features" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:enabled-tools> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasRestrictedValue "UB.DBA.sparqlQuery,Demo.demo.execute_spasql_query,Demo.demo.execute_sql_query" ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> .

oplres:api-entry-modules a oplres:Restriction ;
    schema:name "API Entry: Included modules" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter  <urn:oai:chat:module> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasRestrictedValue "cello-config,data-twingler-config,opml-rss-news-reader,uda-support-assistant-config,virtuoso-support-assistant-config,data-twingler-uniprot" ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> .

# --- Medium Level Features ---

# Adds: Sponge, Facet Search, Web Fetch

oplres:api-medium-tools a oplres:Restriction ;
    schema:name "API Medium: Included Features" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:enabled-tools> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasRestrictedValue "UB.DBA.sparqlQuery,Demo.demo.execute_spasql_query,Demo.demo.execute_sql_query,OAI.DBA.WEB_FETCH,OAI.DBA.SPONGE_URL,FCT.DBA.FacetSearch" ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> .

oplres:api-medium-modules a oplres:Restriction ;
    schema:name "API Medium: Included modules" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter  <urn:oai:chat:module> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasRestrictedValue "cello-config,data-twingler-config,opml-rss-news-reader,uda-support-assistant-config,virtuoso-support-assistant-config,data-twingler-uniprot" ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> .

# --- Advanced Level Features ---
# Adds: Agent Configs (Implied by Module Access, effectively Same tools as Medium + Config permission)

oplres:api-advanced-tools a oplres:Restriction ;
    schema:name "API Advanced: Included Features" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:enabled-tools> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasRestrictedValue "UB.DBA.sparqlQuery,Demo.demo.execute_spasql_query,Demo.demo.execute_sql_query,OAI.DBA.WEB_FETCH,OAI.DBA.SPONGE_URL,FCT.DBA.FacetSearch" ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> .

# --- Max Level Features ---

# System Wide Access - Includes all

oplres:api-max-enable-keys a oplres:Restriction ;
    schema:name "API Max: Enable System-Wide Keys" ;
    oplres:hasRestrictedResource <urn:oai:chat> ;
    oplres:hasRestrictedParameter <urn:oai:chat:enable-api-keys> ;
    oplres:hasRealm oplacl:DefaultRealm ;
    oplres:hasRestrictedValue "1"^^xsd:string ;
    oplres:hasAgent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> .

# ==============================================================================
# Rules
# ==============================================================================

# --- Chat access rule ---

oplacl:chat-access-api-offers a acl:Authorization ;
    schema:name "Rule to allow access to /chat when an offer is purchased" ;
    acl:accessTo <urn:oai:chat> ;
    oplacl:hasAccessMode oplacl:Read, oplacl:Write ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> ;
    oplacl:hasRealm oplacl:DefaultRealm ;
    oplacl:hasScope oplacl:Query .

# --- Rule to access /oauth/clients.vsp ---

oplacl:oauth-apps-access-api-offers a acl:Authorization ;
    schema:name "Rule to allow access to oauth apps when an API offer is purchased" ;
    acl:accessTo <urn:virtuoso:access:oauth:apps> ;
    oplacl:hasAccessMode oplacl:Read, oplacl:Write ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessEntryUsers#this> ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessMediumUsers#this> ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessAdvancedUsers#this> ;
    acl:agent <http://data.openlinksw.com/oplweb/group/ApiAccessMaxUsers#this> ;
    oplacl:hasRealm oplacl:DefaultRealm ;
    oplacl:hasScope oplacl:OAuth .

## --- Graph Access ---
# ==============================================================================
# Conditonal Group Definitions for each offer type
# ==============================================================================

<http://data.openlinksw.com/oplweb/group/DemoGraphAccessUsers#this> a oplacl:ConditionalGroup ;
  foaf:name "Users identified using a NetID based Identifier who have purchased the demo graph access offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:DemoGraphAccessOffer ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) . filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

<http://data.openlinksw.com/oplweb/group/DemoGraphAccessUsersWorldCupMeshup#this> a oplacl:ConditionalGroup ;
  foaf:name "Users identified using a NetID based Identifier who have purchased the demo graph access offer and whose license is in date" ;
  oplacl:hasCondition [
    a oplacl:GroupCondition, oplacl:QueryCondition ;
    oplacl:hasQuery "prefix oplprchs:  <http://www.openlinksw.com/ontology/purchases#>prefix opllic:   <http://www.openlinksw.com/ontology/licenses#>prefix oplofr:    <http://www.openlinksw.com/ontology/offers#>prefix schema:    <http://schema.org/> ask from <urn:openlinksw.com:shop:purchases:cache> where {{select ?purchase where {^{uri}^ oplprchs:madePurchase ?purchase .}} union {select ?purchase where {?o owl:sameAs ^{uri}^ ; oplprchs:madePurchase ?purchase .}} ?purchase oplprchs:contains ?offer ;   oplprchs:purchaseDate ?purchaseDate . ?offer a oplofr:DemoGraphAccessOfferWorldCupMeshup ; schema:itemOffered ?license .  ?license opllic:hasDuration ?duration .  ?duration opllic:durationYears ?years .  filter (bif:dateadd (\'day\', bif:atoi(?years) * 365, ?purchaseDate) > bif:now()) . filter (sql:stripe_customer_has_active_product_subscription (^{uri}^, ?license) > 0) .}"
     ] .

# ==============================================================================
# Restrictions
# ==============================================================================

# --- Limits ---

# ==============================================================================
# Rules
# ==============================================================================

# --- Graph access rule ---

oplacl:demo-graph-access a acl:Authorization ;
  schema:name "Rule to allow access to the demo graph" ;
  acl:accessTo <urn:demo:graph> ;
  oplacl:hasAccessMode oplacl:Read ;
  oplacl:hasRealm oplacl:DefaultRealm ;
  oplacl:hasScope oplacl:PrivateGraphs ;
  acl:agent <http://data.openlinksw.com/oplweb/group/DemoGraphAccessUsers#this> ;
  wdrs:describedby <#source> .

oplacl:demo-graph-access-world-cup-meshup a acl:Authorization ;
  schema:name "Rule to allow access to the <https://linkeddata.uriburner.com/DAV/demos/daas/world-cup-2026-meshup-kg-1.ttl> graph" ;
  acl:accessTo <https://linkeddata.uriburner.com/DAV/demos/daas/world-cup-2026-meshup-kg-1.ttl> ;
  oplacl:hasAccessMode oplacl:Read ;
  oplacl:hasRealm oplacl:DefaultRealm ;
  oplacl:hasScope oplacl:PrivateGraphs ;
  acl:agent <http://data.openlinksw.com/oplweb/group/DemoGraphAccessUsersWorldCupMeshup#this> ;
  wdrs:describedby <#source> .


## --- File Access ---
# ==============================================================================
# Restrictions
# ==============================================================================

# --- Limits ---

# ==============================================================================
# Rules
# ==============================================================================

# --- File access rule ---

# -- TTL file also needs rule to allow the file access users to use /sparql to describe ttl files using the faceted browser?
# -- I have not been able to make this work

oplacl:fct-access a acl:Authorization ;
  schema:name "Rule to allow access to /sparql for user who purchase file access" ;
  acl:accessTo <urn:virtuoso:access:sparql> ;
  oplacl:hasAccessMode oplacl:Read ;
  oplacl:hasRealm oplacl:DefaultRealm ;
  oplacl:hasScope oplacl:Query ;
  acl:agent <http://data.openlinksw.com/oplweb/group/XYZFileAccessUsers#this> ;
  wdrs:describedby <#source> .


## Turtle End ##
